J'ai un fichier d'entrée dans mon application contenant une vaste quantité d'informations. Lecture sur elle séquentiellement, et uniquement un seul décalage de fichier à la fois ne suffit pas pour l'utilisation de mon application. Idéalement, je voudrais avoir deux threads, qui ont une lecture distincte Immédiatement, je peux penser à deux manières, p>
y a-t-il une troisième (ou quatrième) option que je n'ai pas encore pensé à? strong> p>
Évidemment, je suis finalement limité par le disque dur qui devait tourner en arrière, mais ce que je suis intéressé à tirer parti de (si possible), est une mise en cache de disque de niveau d'exploitation dans les deux décalages de fichiers simultanément. P>
Merci. P> ifstream code> S à partir de deux compensations de fichiers uniques du même fichier. Je ne peux pas simplement commencer un
ifstream code> up, puis en effectuer une copie à l'aide de son constructeur de copie (depuis son incord).
ifstream code> pour le deuxième thread, ouvrez-le sur le même fichier. LI>
ifstream code> sur les deux threads (en utilisant par exemple
boost :: Shared_ptr <> code>). Recherchez le décalage du fichier approprié que le thread actuel est actuellement intéressé, lorsque le thread obtient une tranche de temps. LI>
ol>
5 Réponses :
entre les deux, je préférerais la seconde. Avoir deux ouvertures du même fichier peut provoquer une vue incohérente entre les fichiers, en fonction du système d'exploitation sous-jacent. P>
Pour une troisième option, transmettez une référence ou un pointeur brut dans l'autre thread. Tant que la sémantique est qu'un thread "possède" l'Istream, le pointeur brut ou la référence conviennent bien. P>
Notez enfin que sur la grande majorité du matériel, le disque est le goulot d'étranglement, pas la CPU, lors du chargement de fichiers volumineux. L'utilisation de deux threads rendra cela pire em> car vous tournez un accès séquentiel d'accès à un accès aléatoire. Les disques durs typiques peuvent faire peut-être 100 Mo / s séquentiellement, mais de haut sur 3 ou 4 Mo / s d'accès aléatoire. P>
Notez qu'il demande à propos de lisant i> un fichier avec std :: ifstream code>. Il n'aura pas à s'inquiéter de vues incohérentes dans ce cas.
@Cory: C'est vrai dans ce cas particulier. Je pense plus généralement.
Deux Si vous avez un seul std :: ifstream code> Les instances seront probablement la meilleure option ici. Les disques durs modernes sont optimisés pour une grande file d'attente de demandes d'E / S.La lecture à partir de deux
std :: ifstream code> Les instances doivent concurremment donner des performances assez agréables. P>
std :: ifstream code> Vous devrez vous inquiéter de la synchronisation de l'accès à celui-ci, plus il pourrait vaincre la mise en cache d'accès à l'accès séquentielle du système d'exploitation, entraînant des performances plus pauvres. . p>
Ceci est vrai que si l'accès initial était aléatoire. Si l'accès initial était séquentiel, l'accès aléatoire induit par les deux threads ferait pire les choses.
En effet. Il déclare explicitement que la lutte de manière séquentielle n'est pas suffisante. Dans ce cas où il doit effectuer un accès aléatoire, deux demandes simultanées vont être meilleures.
Autre option: p>
Istrstream code> est bon pour cela, istringstream code> n'est pas). LI>
ul>
Votre compilateur doit-il prendre en charge une standard C ++ sur C ++ pour l'utiliser?
@J T: La cartographie de la mémoire n'est pas couverte par la norme. Vous devrez utiliser les appels qu'il faudrait sur votre plate-forme. Sur POSIX, ce sera mmap code>, sous Windows qui sera
CreateFilemapping CODE> +
MapViewOffile code>
La cartographie de la mémoire ne fait pas partie de la norme. Boost Interprocess a un support de cartographie de mémoire multiplate-forme, cependant.
Je pensais std :: strtstream a été obsolète ?
@awoodland: c'est. Et il est aussi obsolète en C ++ 0x. Étant donné que les dépréciations impliquent, "obligatoirement d'être présent dans toute mise en œuvre conforme", nous sommes bons à partir ;-) Une alternative consiste à réécrire le code pour fonctionner directement sur la matrice mappée, plutôt que via un flux, mais en utilisant Istrstream code>, qui est nécessairement en lecture seule, est assez inoffensif.
Mon vote serait un seul lecteur, qui maintient les données à plusieurs threads de travailleurs. p>
Si votre fichier est sur un seul disque, plusieurs lecteurs tueront vos performances de lecture. Oui, votre noyau peut avoir des capacités de mise en cache ou de mise en file d'attente fantastiques, mais il va dépenser plus de temps à la recherche de temps que de lire des données. P>
Il y aura tout autant de recherche sur le disque lorsqu'il recherche dans le fichier. Et la recherche constante de la recherche de stratégies de lecture à l'avance que le système d'exploitation pourrait utiliser.
@ James-Kanze Lecture d'un fichier séquentiellement à partir de 2 processus ou threads différents aura beaucoup plus de disque de disque que d'un processus ou d'un seul processus qui cherche autour du fichier. Analogie: Pensez à 2 personnes à lire du même livre.
Ok, mais dans votre analogie du livre, si une personne célibataire voulait lire simultanément les chapitres 4 et 8, ne devra-t-il pas renvoyer les pages autant de choses autant?
@JT: Oui, mais Lisez Post de OP: .. LIRE. chapitre à la fois. Il peut décider quand retourner à l'autre chapitre.
"Lire le dessus de cela séquentiellement ... n'est pas suffisant"
Cela dépend vraiment de votre système. Un système moderne va généralement lire en avant; La recherche dans le dossier est susceptible d'inhiber cela, alors devrait définitivement être évité. p>
Il peut être utile d'expérimenter la lecture de votre système:
Ouvrez le fichier, puis lisez la première moitié de cela séquentiellement et voyez comment
long qui prend. Puis ouvrez-le, cherchez au milieu et lisez la seconde
mi-séquentiellement. (Sur certains systèmes que j'ai vus dans le passé, un simple
chercher, à tout moment, fera désactiver la lecture.) Enfin, ouvrez-le, puis
lire tous les autres enregistrements; Cela simulera deux threads en utilisant le même
Descripteur de fichier. (Pour tous ces tests, utilisez des enregistrements de longueur fixe et
Ouvrir en mode binaire. Prenez également les mesures nécessaires pour assurer
que toutes les données du fichier sont purgées à partir du cache du système d'exploitation avant
Démarrer le test-sous Unix, copiant un fichier de 10 ou 20 gigaoctets
à Cela vous donnera quelques idées, mais pour être vraiment certain, le meilleur
la solution serait de tester les cas réels. Je serais surpris si partager un
simple Je recommanderais également des solutions spécifiques au système tels que Enfin, serait-il possible d'obtenir les données déjà coupées en
fichiers plus petits? Cela pourrait être la solution la plus rapide de tous. (Idéalement,
cela serait fait lorsque les données sont générées ou importées dans la
système.) p> / dev / null code> est généralement suffisant pour cela. P>
ifstream code> (et donc un seul descripteur de fichier), et constamment
Cherche, gagné, mais vous ne savez jamais. P>
MMAP code>, mais si vous avez
obtenu autant de données, il y a de bonnes chances que vous ne puissiez pas la cartographier
Tout en un va quand même. (Vous pouvez toujours utiliser
mmap code>, des sections de cartographie de celui-ci
à la fois, mais cela devient beaucoup plus compliqué.) p>
C'était un mélange pour votre solution et celle que j'ai sélectionnée. +1