In dieser Antwort möchte ich Ihnen einige Benchmarks zeigen, die drei verschiedene serielle Methoden zum Lesen von Daten in C ++ vergleichen, wobei die dritte die schnellste ist.
Bei der ersten Methode verwende ich einen std :: istreambuf_iterator
, bei der zweiten lese ich die Datei zeilenweise in einen std :: vector
und im dritten verwende ich Operationen mit C-Geschmack.
/ * kompiliere mit g ++ -std = c ++ 11 -O2 Reading_files.cpp -o Reading_filestest das Programm mit dem folgendendd if = / dev / zufällig von =. / dummy5GiB bs = 1024 count = $ [1024 * 1024 * 5] für i in 0 1 2; Zeit nehmen ./reading_files dummy5GiB $ i; getan * / # include <fstream> # include <iostream> # include <vector> # include <cstring> // für strcmp # include <string> # include <algorithm> // für minusing namespace std;! int main (int argc, char * argv []) {if (argc = 3) {cerr << "Verwendung: Lesedateien <path> <number 0 oder 1 oder 2> \ n"; return 1; } ifstream-Datei (argv [1], ios :: in | ios :: binary); if (! file.is_open ()) {cerr << argv [1] << "Datei nicht geöffnet! \ n"; return 1; } cout << "--------------------------- \ n"; if (! strcmp (argv [2], "0")) {cout << "method 0 \ n"; vector<char> content ((std :: istreambuf_iterator<char> (Datei)), std :: istreambuf_iterator<char> ()); cout << content.size () << "Bytes gelesen \ n"; } else if (! strcmp (argv [2], "1")) {cout << "Methode 1 \ n"; String Line; vector<string> Inhalt; while (getline (Datei, Zeile)) {content.push_back (Zeile); }}
cout << content.size () << "Zeilen gelesen \ n"; } else if (! strcmp (argv [2], "2")) {cout << "Methode 2 \ n"; file.seekg (0, std :: ios :: end); unsigned long long file_size = file.tellg (); cout << "Dateigröße ist" << Dateigröße << "\ n"; // maximal 5 GiB Speicher, also passend zu meinem RAM unsigned long long max_block_size = 1024ULL * 1024ULL * 1024ULL * 5; file.clear (); file.seekg (0, std :: ios :: beg); unsigned long long block_size = min (max_block_size, file_size); char * buffer = (char *) malloc (block_size * sizeof (char)); vorzeichenlos lang lang verarbeitet = 0; while (! file.eof ()) {file.read (buffer, block_size); cout << "lese einen Block von" << min (Dateigröße - verarbeitet, Blockgröße) << "Bytes \ n"; // arbeite hier mit dem Block im Speicher (wenn die Blockgröße > 0 ist) verarbeitet + = block_size; } free (Puffer); } file.close (); return 0;}
Bei der dritten Methode habe ich die Datei in Blöcken von 5 GB gelesen, um sie an den freien Arbeitsspeicher meines Computers anzupassen.
Hier ist der Benchmark von das Programm in einer zufällig generierten 5-GiB-Datei.
bash-3.2 $ für i in 0 1 2; Zeit nehmen ./reading_files dummy5GiB $ i; erledigt --------------------------- Methode 05368709120 Bytes readreal 0m35.194suser 0m19.665ssys 0m12.999s --------- ------------------ Methode 120973135 Zeilen readreal 0m40.478suser 0m34.046ssys 0m5.870s ------------------- -------- Methode 2Dateigröße ist 5368709120Lesen Sie einen Block von 5368709120 Bytesread Einen Block von 0 Bytesreal 0m4.413suser 0m1.757ssys 0m2.617s
Hier ist der Benchmark für eine echte 32-GB-BAM-Datei, bei der nur die dritte Methode verwendet wird. Hier spielt die Aufteilung der gelesenen Datei eine grundlegende Rolle. Ich kann Ihnen nicht sagen, wie groß mein Festplattenspeicher vor dem Ende der Ausführung ist und ich das Programm beenden muss.
time ./reading_files ./HG00252.mapped. ILLUMINA.bwa.GBR.low_coverage.20130415.bam 2 --------------------------- Methode 2Die Dateigröße beträgt 34316054058Lesen Sie einen Block mit 5368709120 Bytesread a Block von 5368709120 Bytesread ein Block von 5368709120 Bytesread ein Block von 5368709120 Bytesread ein Block von 5368709120 Bytesread ein Block von 5368709120 Bytesread ein Block von 2103799338 Bytesreal 0m50.656suser 0m9.135ssys 0m35.728s
Der wichtigste Punkt besteht darin, die Dateivorgänge zu minimieren, die große Datenblöcke gleichzeitig lesen (solange sie in den Speicher passen) und sie zu bearbeiten.
Die Verwendung von mmap
kann zu einer Verbesserung führen , aber ich denke nicht, dass es so groß wäre wie die dritte Methode anstelle der ersten beiden.