Stratégies d'E / S pour les problèmes de calcul avec de grands ensembles de données?

15

Mon groupe de recherche se concentre sur la dynamique moléculaire, qui peut évidemment générer des gigaoctets de données dans le cadre d'une trajectoire unique qui doit ensuite être analysée.

Plusieurs des problèmes qui nous préoccupent impliquent des corrélations dans l'ensemble de données, ce qui signifie que nous devons garder une trace de grandes quantités de données en mémoire et les analyser, plutôt que d'utiliser une approche plus séquentielle.

Ce que j'aimerais savoir, ce sont les stratégies les plus efficaces pour gérer les E / S de grands ensembles de données dans des scripts. Nous utilisons normalement des scripts basés sur Python car cela rend le codage des E / S de fichiers beaucoup moins pénible que C ou Fortran, mais lorsque nous avons des dizaines ou des centaines de millions de lignes à traiter, la meilleure approche n'est pas si claire. . Devrions-nous envisager de faire la partie d'entrée de fichier du code en C, ou une autre stratégie est-elle plus utile? (Le simple préchargement de l'ensemble de la baie en mémoire sera-t-il meilleur qu'une série de lectures séquentielles de "morceaux" (ordre de mégaoctets)?

Quelques notes supplémentaires:

  • Nous recherchons principalement des outils de script pour le post-traitement, plutôt que des outils "en ligne" - d'où l'utilisation de Python.

  • Comme indiqué ci-dessus, nous faisons des simulations MD. Un sujet d'intérêt est le calcul de diffusion, pour lequel nous devons obtenir le coefficient de diffusion d'Einstein: Cela signifie que nous devons vraiment charger toutes les données en mémoire avant de commencer le calcul - tous les morceaux de données ( enregistrements de temps individuels) interagiront les uns avec les autres.

    =16limΔt(X(t+Δt)-X(t))2
aeismail
la source

Réponses:

6

Je suppose que votre question vient de l'observation que les E / S entraînent une surcharge importante dans l'ensemble de votre analyse. Dans ce cas, vous pouvez essayer de chevaucher les E / S avec le calcul.

Une approche réussie dépend de la façon dont vous accédez aux données et du calcul que vous effectuez sur ces données. Si vous pouvez identifier un modèle, ou si l'accès à différentes régions des données est connu à l'avance, vous pouvez essayer de pré-extraire les «prochains morceaux» de données en arrière-plan pendant le traitement des «morceaux actuels».

À titre d'exemple simple, si vous ne parcourez votre fichier qu'une seule fois et traitez chaque ligne ou ensemble de lignes, vous pouvez diviser le flux en morceaux de lignes (ou Mo). Ensuite, à chaque itération sur les blocs, vous pouvez charger le bloc i + 1 pendant le traitement du bloc i.

Votre situation peut être plus complexe et nécessiter des solutions plus impliquées. Dans tous les cas, l'idée est d'effectuer les E / S en arrière-plan pendant que le processeur a des données sur lesquelles travailler. Si vous donnez plus de détails sur votre problème spécifique, nous pourrons peut-être approfondir le sujet;)

---- Version étendue après avoir donné plus de détails ----

Je ne suis pas sûr de comprendre la notation, mais bon, comme vous l'avez dit, l'idée est une interaction tout-à-tout. Vous mentionnez également que les données peuvent tenir dans la RAM. Ensuite, je commencerais par mesurer le temps pour charger toutes les données et le temps pour effectuer le calcul. Maintenant,

  • si le pourcentage des E / S est faible (faible comme vous ne vous souciez pas de la surcharge, quelle qu'elle soit: 0,5%, 2%, 5%, ...), alors utilisez simplement l'approche simple: charger les données à la fois, et calculer. Vous gagnerez du temps pour des aspects plus intéressants de votre recherche.

  • si vous ne pouvez pas vous permettre les frais généraux, vous voudrez peut-être examiner ce que Pedro a suggéré. Gardez à l'esprit ce qu'Aron Ahmadia a mentionné et testez-le avant de procéder à une implémentation complète.

  • si les précédents ne sont pas satisfaisants, j'opterais pour une mise en œuvre hors noyau [1]. Puisqu'il semble que vous effectuez calculs sur données, il y a de l'espoir :) Certains pseudocodes (en supposant que les résultats de votre analyse tiennent dans la RAM):n2n

    charger chunk1 et chunk2
    pour les morceaux i = 1 à n
        charger de façon asynchrone le bloc i + 1
        pour les morceaux en j = i + 1 à n
            charger de manière asynchrone le bloc j + 1
            calculer avec les morceaux i, j (* pour la première itération, ce sont les morceaux préchargés 1 et 2 *)

Remarque: il s'agit d'un pseudocode rapide et sale, il faudrait ajuster les indices.

Pour implémenter cela, il est courant d'utiliser ce que l'on appelle la double mise en mémoire tampon . En gros: divisez la mémoire en deux espaces de travail; tandis que les données sont chargées en arrière-plan dans l'espace de travail 1, le processeur calcule les données dans l'espace de travail 2. À chaque itération, échangez le rôle.

Je suis désolé de ne pas pouvoir trouver une bonne référence pour le moment.

[1] Un algorithme hors cœur incorpore un mécanisme pour traiter (efficacement) les données résidant sur le disque. Ils sont appelés out-of-core par opposition à in-core ("in-RAM").

Diego
la source
7

J'ai déjà dû faire face à des problèmes similaires, et ma solution préférée est d'utiliser les E / S mappées en mémoire , bien qu'en C ...

Le principe sous-jacent est assez simple: au lieu d'ouvrir un fichier et de le lire, vous le chargez directement dans la mémoire et y accédez comme s'il s'agissait d'un énorme tableau. L'astuce qui le rend efficace est que le système d'exploitation ne charge pas réellement le fichier , il le traite simplement comme de la mémoire échangée qui doit être chargée. Lorsque vous accédez à un octet donné dans votre fichier, la page mémoire de cette partie du fichier est permutée en mémoire. Si vous continuez à accéder à différentes parties du fichier et que la mémoire est restreinte, les parties les moins utilisées seront remplacées - automatiquement!

Une recherche rapide sur Google m'indique que cela est également disponible pour Python: 16.7. mmap - Prise en charge des fichiers mappés en mémoire , mais je ne connais pas suffisamment Python pour savoir si c'est vraiment la même chose.

Pedro
la source
1
Assurez-vous simplement de mesurer et de tester avant d'implémenter quelque chose comme mmapdans votre code principal. De nombreux systèmes d'exploitation modernes offrent des performances similaires entre les standards readavec moins de complications. (De plus, oui, mmap en Python fournit une interface portable avec les cartes mémoire Windows et UNIX).
Aron Ahmadia
1

Peut-être pouvez-vous utiliser Cython dans vos sections d'E / S de fichiers et convertir cette partie en code C?

asmatique
la source