Moyen efficace de sauvegarder des données sur le disque tout en exécutant une tâche de calcul intensif

StackOverflow https://stackoverflow.com/questions/1014113

Question

Je travaille sur un logiciel scientifique très gourmand en ressources processeur (lié à la procédure), mais il doit écrire assez souvent les données sur le disque (lié à l'entrée / la sortie).

J'ajoute de 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’ya aucune raison que la simulation attende sur le disque dur (ce qu’elle fait maintenant).

Je recherche 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

Premières pensées:

ayant un processus séparé, écrit sur le disque pour que la simulation comporte deux processus: l’un est lié à la CPU (simulation) et l’autre est lié à IO (fichier d’écriture). Cela semble compliqué.

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

Était-ce utile?

La solution

Si vous implémentez OpenMP dans votre programme, il est préférable d'utiliser #pragma omp single ou #pragma omp master de la section parallèle pour enregistrer dans un fichier. Ces pragmas permettent à un seul thread d'exécuter quelque chose. Votre code peut donc ressembler à ce qui 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
}

Ici, l'équipe de threads fera le calcul, mais seul un thread sauvegardera les résultats sur le disque.

Cela ressemble à un pipeline de logiciels. Je vous suggère d’envisager le modèle tbb :: pipeline de la bibliothèque Intel Threading Building Blocks. Je vous renvoie au tutoriel sur les pipelines de logiciels à l'adresse 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, un second à traiter les chaînes de lecture, un troisième à enregistrer sur le lecteur.

Autres conseils

Je dirais que le meilleur moyen serait de créer un autre thread pour sauvegarder les données, et non un processus complètement nouveau. avec un nouveau processus, vous rencontrez le problème de devoir communiquer les données à enregistrer de part et d'autre de la limite du processus, ce qui introduit de nouvelles difficultés.

La première solution qui vous vient à l’esprit est à peu près ce que vous avez dit: avoir des écritures sur disque dans leur propre processus avec un tuyau à sens unique allant de la sim à l’écrivain. Le rédacteur écrit aussi vite que possible (en extrayant de nouvelles données). Le problème, c’est que si la sim va trop loin devant l’écrivain, elle va bloquer de toute façon sur le tuyau écrit, et ce sera lié à une entrée / sortie bloquée.

Le problème, c’est qu’en fait, votre cycle de simulation n’est pas achevé tant que les résultats ne sont pas crachés.

La deuxième chose qui me vient à l’esprit est d’utiliser des E / S non bloquantes. Chaque fois que la sim a besoin d'écrire, elle doit le faire via des E / S non bloquantes. Lors du prochain besoin d’écriture, il peut ensuite récupérer les résultats de la précédente opération d’E / S (ce qui peut entraîner une petite attente) avant de commencer la nouvelle. Cela permet à la simulation de fonctionner autant que possible en parallèle avec les E / S sans lui laisser une longueur d’avance sur l’écriture.

La première solution serait préférable si le cycle de traitement de la simulation varie (parfois plus petit que le temps nécessaire pour une écriture, parfois plus long) car, en moyenne, les écritures peuvent suivre la sim.

Si le cycle de traitement est toujours (ou presque toujours) plus court que le temps d'écriture  Dans ce cas, vous pouvez également ne pas vous soucier de la conduite et utiliser uniquement des E / S non bloquantes, car si vous utilisez la conduite, elle finira par se remplir et la carte SIM restera bloquée sur les E / S.

Puisque vous êtes lié au processeur et aux entrées-sorties: laissez-moi deviner: il reste encore beaucoup de mémoire disponible, non?

Si tel est le cas, vous devez mettre en mémoire tampon les données à écrire sur le disque dans une certaine mesure. L'écriture de gros morceaux de données est généralement beaucoup plus rapide que l'écriture de petits morceaux.

Pour l'écriture proprement dite: envisagez d'utiliser des entrées / sorties mappées en mémoire. Cela fait un moment que je n'ai pas mesuré, mais la dernière fois, c'était beaucoup plus rapide.

De plus, vous pouvez toujours échanger un peu de CPU contre IO. Je pense que vous écrivez actuellement les données sous forme de données brutes, non compressées, non? Vous pouvez obtenir des performances IO 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 ya beaucoup de redondance, même un algorithme de compression très grossier pourrait éliminer le problème lié aux entrées / sorties.

Un thread exécute en permanence une étape du processus exigeant en calculs, puis ajoute le résultat partiel à une file d'attente de résultats partiels. Un autre thread supprime continuellement 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 semblable à une liste dans laquelle vous pouvez ajouter des éléments à la fin et supprimer des éléments de l'avant.

Faites en sorte que votre application comporte deux threads , un pour le processeur et un pour le disque dur.

Demandez au thread de la CPU de placer les données terminées dans une file d'attente à partir de laquelle le thread de disque dur extrait au fur et à mesure que les données arrivent.

Ainsi, le processeur se débarrasse simplement des données et laisse le soin à quelqu'un d'autre de les gérer. Le disque dur attend patiemment toutes les données de sa file d'attente.

Du point de vue de la mise en œuvre, vous pouvez créer la file d’attente en tant qu’objet de type mémoire partagée, mais je pense qu’un tuyau correspondrait exactement à ce que vous recherchez. Le processeur écrit simplement sur le tuyau en cas de besoin. Du côté du disque dur, il vous suffira de lire le tuyau et à partir de là, chaque fois que vous obtiendrez des données valides.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top