J'ai un programme qui lit les données de 2 fichiers texte, puis enregistrez le résultat à un autre fichier. Comme il existe de nombreuses données à lire et à écrire qui causent une performance frappée, je souhaite paralliser les opérations de lecture et d'écriture. P>
Ma pensée initiale est, utilisez 2 threads à titre d'exemple, un fil en lecture / écriture du début, et un autre fil en lecture / écriture du milieu du fichier. Étant donné que mes fichiers sont formatés comme des lignes, pas d'octets (chaque ligne peut avoir différents octets de données), rechercher par octet ne fonctionne pas pour moi. Et la solution que je pouvais penser est d'utiliser GetLine () pour ignorer d'abord les lignes précédentes, ce qui pourrait être efficace. P>
Y a-t-il un bon moyen de chercher à une ligne spécifiée dans un fichier? ou avez-vous d'autres idées pour paralliser la lecture et l'écriture de fichiers? p>
Environnement: Win32, C ++, NTFS, un seul disque dur P>
merci. p>
-DBger p>
3 Réponses :
En règle générale, vous ne voulez pas parlementer des E / S du disque. Les disques durs n'aiment pas les E / S aléatoires car ils doivent continuellement chercher à accéder aux données. En supposant que vous n'utilisez pas RAID et que vous utilisez des lecteurs durs par opposition à une mémoire d'état solide, vous verrez une grave dégradation des performances si vous parallélisez les E / S (même lorsque vous utilisez des technologies comme celles-ci, vous pouvez toujours voir des performances. dégradation lorsque vous faites beaucoup d'E / S aléatoires). P>
Pour répondre à votre deuxième question, il n'est vraiment pas un bon moyen de rechercher une certaine ligne dans un fichier; Vous pouvez uniquement rechercher explicitement un décalage d'octet à l'aide de la fonction lisez code> (voir Cette page Pour plus de détails sur la façon de l'utiliser. P>
Donc, dans la lecture / écriture de fichier, le disque recherche la plupart du temps, ce qui est le cas dans l'environnement multi-threading, est-ce correct?
Oui, le temps de recherche du disque sera généralement le goulot d'étranglement d'un environnement d'E / S multithread. Vous devriez essayer de sérialiser vos E / S si possible.
Merci Mike, juste pour confirmer, est-ce que cela ne s'applique que lors de la lecture d'un fichier unique, ou s'applique également lors de la lecture de fichiers multiples (fil de lecture 1 File1, filed Lecture File2)
Ce que j'ai dit s'applique à n'importe quel disque d'E / S sur un seul disque, qu'il existe des fichiers distincts. Bien entendu, la mise en cache du système d'exploitation ou du disque aura un effet sur les résultats réels.
Mais il existe des systèmes de fichiers qui vous permettent de distribuer des fichiers sur différentes sections de disque / disque afin de réduire linéairement vos E / S.
Ce n'est pas vraiment une réponse à votre question, mais plutôt une nouvelle conception (que nous détestons tous mais ne peut pas aider à faire). Comme déjà mentionné, essayant d'accélérer les E / S sur un disque dur avec plusieurs threads ne vous aidera probablement pas. p>
Cependant, il pourrait être possible d'utiliser une autre approche en fonction de la sensibilité des données, des besoins du débit, de la taille des données, etc. Il ne serait pas difficile de créer une structure en mémoire qui maintient une image des données et permet des mises à jour faciles / rapides. des lignes de texte n'importe où dans les données. Vous pouvez ensuite utiliser un fil dédié qui surveille simplement cette structure et dont le travail est d'écrire les données sur le disque. Les données d'écriture séquentiellement sur le disque peuvent être extrêmement rapides; Cela peut être beaucoup plus rapide que de rechercher au hasard à différentes sections et de l'écrire en morceaux. P>
Lorsque j'écris environ 2 m de données dans un fichier texte, séquentiellement, cela coûte environ 1 seconde sur ma machine, qui est trop lent pour moi. En ce qui concerne la lecture, afin de former une structure de mémoire du fichier, j'ai besoin de lire les données en premier, ce qui est également trop lent pour répondre à mes besoins. Cependant, j'éditionnerais sur les sujets sur le fichier I / O et MemoryMap Fichier pour voir si cela aide.
1 seconde pour écrire 2 Mo? Cela semble étonnamment lent. Je viens de courir un test qui écrit 10m à un fichier d'environ 100 ms et que mon PC n'est pas une machine de vitesse réelle (3.2GHz et i pense i> 7200RPM lecteur). Quelles API utilisez-vous pour ouvrir et écrire dans le fichier avec?
J'utilise STD :: destream pour économiser beaucoup de données séparées dans une boucle. comme "pour (...) {streamout << x; streamout << y}", et j'ai aussi un lecteur de 7200RPM avec une CPU à double noyau 2.16GHz
C'est intéressant. Si j'ai du temps, je devrais devoir tester cela sur mon PC par curiosité. J'utilisais simplement les API Win32 (Createfile, Wrardfile). Mais en réalité, je m'attendrais à ce que la Streamio passe par ces API sur Win32. Ou sinon, cela serait toujours à travers une sorte d'E / S tamponnée. La latence moyenne d'un disque de 7200 tr / min doit être inférieure à 5 ms. Cela devrait permettre de nombreuses écritures tamponnées. Je suppose que si le disque était complètement fragmenté dans 4096 morceaux, il serait sur 1 seconde / MB.
Markw, il s'avère que la plupart du temps dépend de la chaîne formant lors de l'appelant "StreamOut << x <<" "" << Y << "" << DL << endl ". J'ai ensuite changé le code pour formater toutes ces données dans une chaîne d'abord, puis écrivez au fichier tout en une fois, cela coûte environ 24 ms pour écrire des données 2M. Ensuite, en parallèle la chaîne formant, il y a un gain de performance notable. Merci beaucoup.
Frais. Je suis content que tu l'as arrêté. Ces chiffres ont beaucoup plus de sens. Merci de reporter de nouveau dessus. J'étais curieux mais jamais eu le temps de le tester.
Queue de lecture multiple et écrivez ne vous aidera pas lorsque vous exécutez un disque sur un disque. Si votre application a également effectué beaucoup de travail dans la CPU, vous pouvez effectuer vos lectures et écrit de manière asynchrone et laisser le processeur de la CPU pendant que le disque d'E / S se produit en arrière-plan. Alternativement, obtenez un deuxième disque dur physique: lisez-en un, écrivez à l'autre. Pour des ensembles de données modestement de la taille, souvent efficaces et toutaux moins chers que le code d'écriture. P>
Utilisez un fil d'arrière-plan pour écrire les données de sortie progressivement lorsque la CPU est occupée avec l'informatique, c'est une bonne idée. Mais pour lire, il ne peut pas être fait que les données ne sont pas prêtes.
DGGER, cela dépend de la nature de vos données. Si vous êtes capable de faire la queue une seconde extraction asynchrone pour être satisfaite lors du traitement des données de la première Fetch, vous travaillez. Encore une fois, il est plus efficace si le disque n'est pas occupé avec d'autres E / S, donc éventuellement non applicable à votre situation immédiate.
Quel est votre système de fichiers et quel matériel utilisez-vous? Si vous n'avez qu'un contrôleur / disque, il peut ne pas être efficace de faire des E / S parallèles
Cela signifie que signifie paralliser le disque d'E / S provoquera toujours une dégradation des performances si on ne fait que lire / écrire sur le même disque?
DBGER: Si vous utilisez un disque dur, oui.
Si vous traitez des fichiers, vous pouvez envisager d'envisager de se chevaucher d'E / S et de calcul. Si vous voulez vraiment essayer parallèlement, vous pouvez diviser vos fichiers en segments (logiquement), chercher à ce segment, trouver le début de la ligne dans le segment et lire jusqu'au segment suivant.
@known, je ne connaissais pas grand chose à propos de "Fichiers divisés en segments", mais si l'E / S du disque préfère l'accès séquentiel, la segmentation devra-t-elle fonctionner?
Non, mais c'est ainsi que vous pourriez le faire parallèlement, au cas où vous voudriez jouer avec elle. Je ne veux pas dire segmentation littérale, je voulais dire lire / traverser un fichier dans des segments,
serverfault.com/questions/826163/...