c++ - terminale - équilibre acido basique définition




Quand créer votre propre système tampon pour les E/S(C++)? (5)

Je dois traiter de très gros fichiers texte (2 Go), il est obligatoire de les lire / écrire ligne par ligne. Ecrire 23 millions de lignes en utilisant ofstream est vraiment lent alors, au début, j'ai essayé d'accélérer le processus en écrivant de gros morceaux de lignes dans un tampon mémoire (par exemple 256 Mo ou 512 Mo) puis d'écrire le tampon dans le fichier . Cela n'a pas fonctionné, la performance est plus ou moins la même. J'ai le même problème en lisant les fichiers. Je sais que les opérations d'E / S sont mises en mémoire tampon par le système d'E / S STL et cela dépend également de la politique du planificateur de disque (gérée par le système d'exploitation, dans mon cas Linux).

Une idée sur la façon d'améliorer la performance?

PS: Je pensais utiliser un processus fils d'arrière-plan (ou un thread) pour lire / écrire les blocs de données pendant que le programme traite les données mais je ne sais pas (surtout dans le cas du sous-processus) si cela en vaudra la peine.


Un fichier de 2 Go est assez volumineux, et vous devez être conscient de toutes les zones possibles qui peuvent agir comme des goulots d'étranglement:

  • Le disque dur lui-même
  • L'interface HDD (IDE / SATA / RAID / USB?)
  • Système d'exploitation / système de fichiers
  • Bibliothèque C / C ++
  • Votre code

Je commencerais par faire quelques mesures:

  • Combien de temps votre code prend-il pour lire / écrire un fichier de 2 Go,
  • À quelle vitesse la commande ' dd ' peut-elle lire et écrire sur le disque? Exemple...

    dd if=/dev/zero bs=1024 count=2000000 of=file_2GB

  • Combien de temps faut-il pour écrire / lire en utilisant simplement les gros appels fwrite () / fread ()

En supposant que votre disque est capable de lire / écrire à environ 40 Mo / s (ce qui est probablement un chiffre réaliste à partir de), votre fichier de 2 Go ne peut pas courir plus de 50 secondes.

Combien de temps cela prend-il réellement?

Salut Roddy, en utilisant la méthode de lecture fstream avec des fichiers de 1,1 Go et de grands tampons (128,255 ou 512 Mo), cela prend environ 43-48 secondes et il en est de même avec fstream getline (ligne par ligne). cp prend presque 2 minutes pour copier le fichier.

Dans ce cas, vous êtes lié au matériel. cp doit lire et écrire, et va chercher à travers la surface du disque comme un fou quand il le fait. Donc, comme vous le voyez, il sera plus de deux fois plus mauvais que le simple cas de «lecture».

Pour améliorer la vitesse, la première chose que je vais essayer est un disque dur plus rapide, ou un SSD.

Vous n'avez pas dit ce qu'est l'interface du disque? SATA est à peu près l'option la plus facile / la plus rapide. Aussi (point évident, ceci ...) assurez-vous que le disque est physiquement sur la même machine que votre code, sinon vous êtes connecté au réseau ...


Je suggèrerais aussi des fichiers mappés en mémoire, mais si vous utilisez boost, je pense que boost :: iostreams :: mapped_file correspond mieux à boost :: interprocess.


L'utilisation de getline () peut s'avérer inefficace car il se peut que le tampon de chaîne doive être redimensionné plusieurs fois à mesure que des données lui sont ajoutées à partir du tampon de flux. Vous pouvez rendre ceci plus efficace en pré-dimensionnant la chaîne:

Aussi, vous pouvez définir la taille de la mémoire tampon iostreams soit très grande ou NULL (pour unbuffered)

// Unbuffered Accesses:
fstream file;
file.rdbuf()->pubsetbuf(NULL,0);
file.open("PLOP");

// Larger Buffer
std::vector<char>  buffer(64 * 1024 * 1024);
fstream            file;
file.rdbuf()->pubsetbuf(&buffer[0],buffer.size());
file.open("PLOP");

std::string   line;
line.reserve(64 * 1024 * 1024);

while(getline(file,line))
{
    // Do Stuff.
}

Peut-être que vous devriez regarder dans les fichiers mappés en mémoire.

Vérifiez-les dans cette bibliothèque: Boost.Interprocess


N'utilisez pas new pour allouer le buffer comme ça:

Essayez: std :: vector <>

unsigned int      buffer_size = 64 * 1024 * 1024; // 64 MB for instance.
std::vector<char> data_buffer(buffer_size);
_file->read(&data_buffer[0], buffer_size);

Lisez aussi l'article sur l' utilisation du trait de soulignement dans les noms d'identifiants:. Notez que votre code est OK mais.







buffer