2009-06-18 6 views
5

Je travaille sur un logiciel scientifique très gourmand en ressources (son processus lié), mais il a besoin d'écrire des données sur disque assez souvent (i/o lié).Manière efficace de sauvegarder des données sur un disque pendant une tâche de calcul intensif

J'ajoute la parallélisation à cela (OpenMP) et je me demande quel est le meilleur moyen de répondre aux besoins d'écriture sur disque. Il n'y a aucune raison que la simulation devrait attendre sur le disque dur (ce qui est ce qu'il fait maintenant).

Je suis à la recherche d'une «meilleure pratique» pour cela, et la vitesse est ce qui me tient le plus à cœur (ces simulations peuvent être extrêmement longues).

Merci ~ Alex

pensées Première:

ayant un processus distinct faire de l'écriture réelle sur le disque de sorte que la simulation a deux processus: l'un est lié au processeur (simulation) et on est IO-lié (fichier d'écriture). Cela semble compliqué.

Peut-être un tuyau/tampon? Je suis un peu nouveau à ceux-ci, alors peut-être que cela pourrait être une solution possible.

Répondre

2

Si vous OpenMP la mise en œuvre de votre programme, il est préférable d'utiliser #pragma omp simple ou #pragma OMP maître de la section parallèle à enregistrer le fichier. Ces pragmas permettent à un seul thread d'exécuter quelque chose. Donc, vous codez peut se présenter comme suit:

#pragma omp parallel 
{ 
    // Calculating the first part 
    Calculate(); 

    // Using barrier to wait all threads 
    #pragma omp barrier 

    #pragma omp master 
    SaveFirstPartOfResults(); 

    // Calculate the second part 
    Calculate2(); 

    #pragma omp barrier 

    #pragma omp master 
    SaveSecondPart(); 

    Calculate3(); 

    // ... and so on 
} 

Voici l'équipe de fils fera le calcul, mais seul thread enregistre les résultats sur le disque.

Cela ressemble à un pipeline logiciel. Je vous suggère de considérer le modèle tbb :: pipeline à partir de la bibliothèque Intel Threading Building Blocks. Je peux vous référer au tutoriel sur les pipelines logiciels au http://cache-www.intel.com/cd/00/00/30/11/301132_301132.pdf#page=25. Veuillez lire le paragraphe 4.2. Ils ont résolu le problème: un thread à lire à partir du lecteur, le second à traiter les chaînes de lecture, le troisième à enregistrer pour conduire.

5

Je dirais que le meilleur moyen serait de générer un thread différent pour enregistrer les données, pas un processus complètement nouveau; Avec un nouveau processus, vous avez la difficulté d'avoir à communiquer les données à sauvegarder à travers les limites du processus, ce qui introduit un nouvel ensemble de difficultés.

0

Un thread exécute en permanence une étape du processus de calcul intensif, puis ajoute le résultat partiel à une file d'attente de résultats partiels. Un autre thread supprime en permanence les résultats partiels de la file d'attente et les écrit sur le disque. Assurez-vous de synchroniser l'accès à la file d'attente. Une file d'attente est une structure de données de type liste dans laquelle vous pouvez ajouter des éléments à la fin et supprimer des éléments du recto.

1

Depuis que vous êtes CPU et IO lié: Laissez-moi deviner: Il y a encore beaucoup de mémoire disponible, non?

Si tel est le cas, vous devez mettre en mémoire tampon les données qui doivent être écrites sur le disque dans une certaine mesure. Ecrire d'énormes morceaux de données est généralement beaucoup plus rapide que d'écrire de petits morceaux.

Pour l'écriture elle-même: pensez à utiliser des E/S mappées en mémoire. Ça fait longtemps que je n'ai pas fait de benchmark, mais la dernière fois que je l'ai fait, c'était plus rapide.

Vous pouvez également toujours échanger du CPU contre IO un peu. Je pense que vous écrivez actuellement les données sous forme de données brutes non compressées, n'est-ce pas? Vous pouvez obtenir des performances d'E/S si vous utilisez un schéma de compression simple pour réduire la quantité de données à écrire. La bibliothèque ZLIB est assez facile à utiliser et compresse très rapidement au niveau de compression le plus bas. Cela dépend de la nature de vos données, mais s'il y a beaucoup de redondance, même un algorithme de compression très brut peut éliminer le problème lié aux E/S.

3

La première solution qui vient à l'esprit est à peu près ce que vous avez dit - avoir le disque écrit dans son propre processus avec un tuyau unidirectionnel de la sim à l'écrivain. L'auteur écrit aussi vite que possible (en tirant de nouvelles données de la pipe). Le problème avec ceci est que si le sim va trop loin devant l'auteur, le sim va bloquer sur les écritures de pipe de toute façon, et il sera lié aux E/S à une suppression. Le problème est que, en fait, votre cycle de simulation n'est pas terminé tant qu'il n'a pas craché les résultats.

La deuxième chose qui me vient à l'esprit est d'utiliser des E/S non bloquantes.Chaque fois que la simulation doit écrire, elle doit le faire via des E/S non bloquantes. Lors du prochain besoin d'écriture, il peut alors récupérer les résultats de l'opération précédente d'E/S (en encourageant peut-être une petite attente) avant de commencer le nouveau. Cela permet à la simulation de fonctionner autant que possible parallèlement à l'E/S sans laisser la simulation prendre une longueur d'avance sur l'écriture.

La première solution serait meilleure si le cycle de traitement de la simulation varie (parfois plus petit que le temps d'écriture, parfois plus long) car en moyenne les écritures pourraient suivre la simulation.

Si le cycle de traitement est toujours (ou presque) plus court que le temps d'écriture alors vous pouvez aussi ne pas vous embêter avec le tuyau et utiliser simplement des E/S non bloquantes, car si vous utilisez le tuyau il finira par se remplir et la carte SIM sera accrochée sur l'E/S de toute façon.

+0

Je pense que le tuyau unidirectionnel est la façon dont j'irai alors. Je ne pense pas que je vais rencontrer la question de bloquer trop mal; theres pas beaucoup de données générées, je voulais juste séparer les discussions. Si je produisais autant de données, je reconsidérerais ce qui doit vraiment être conservé. – machinaut

0

Faites votre application avoir deux threads, un pour le processeur et un pour le disque dur.

Demandez la poussée de thread CPU terminé les données dans une file d'attente que le fil de disque dur tire alors à partir des données entre en jeu.

De cette façon, la CPU se vient débarrasser des données et permet à quelqu'un d'autre le manipuler et le disque le lecteur attend patiemment toutes les données dans sa file d'attente. En ce qui concerne l'implémentation, vous pouvez faire de la file d'attente un type d'objet à mémoire partagée, mais je pense qu'un tube correspond exactement à ce que vous recherchez. Le processeur écrit simplement sur le tube si nécessaire. Du côté du disque dur, vous devriez simplement lire le tuyau et chaque fois que vous avez des données valides, continuez à partir de là.

Questions connexes