быстрое чтение файлов в C ++, сравнение различных стратегий с интерпретацией результатов производительности mmap () и std :: cin () - PullRequest
1 голос
/ 27 марта 2019

После советов по вопросу, который я сделал, чтобы закрыть mmapped файлы ( c ++, закрыть файл open (), прочитанный с помощью mmap ), я провел несколько сравнений и заметил, что, как предлагают некоторые пользователи, std :: Подход cin-буфера работает аналогично моему подходу mmapped.

Я решил провести сравнение производительности: каждый сценарий открывает файл, содержащий путь к другим файлам (около 3500), читает файл и принимает 10 случайных путей и открывает все эти 10 файлов (по 500 строк каждый, по 700 символов каждый). строка) и прочитайте количество строк в ней, 1000 раз случайным образом.

В моей исходной версии был сопоставленный подход (но он не закрывал файл в конце и выдает ошибку после 300-400 открытий файла, в данном случае не достигается ( c ++ закрывает файл open ()) читать с помощью mmap )).

MMAP.OPEN (v0) :

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <set>
#include <typeinfo>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fstream>
#include <sstream>
#include <unistd.h>

const char* map_file(const char* fname, size_t& length);
void  gnomadIndex( std::string &nomeFileIndex,
                    std::vector<std::string> &vSubfileNames,
                    std::vector<int> &vSubfileStarts,
                    std::vector<int> &vSubfileStops,
                    std::vector<std::vector<int>> &vSubfilePosizioniVector);
void gnomadSubfileAnalysis( std::string &nomeFile );
void populateVector( std::vector<int> &vec, int n );
int generateRandInt( int l0, int u0 );

int main() {

      //this take the INDEX file (with the paths to the athor) and populate these vectors
      std::string gnomadSplitDir = "/Volumes/enrico/gnomad/exomes/splitted_5c/";
      std::string nomeChr = "1";
      std::stringstream streamNomeGnomadChrDir;
      streamNomeGnomadChrDir << gnomadSplitDir << "ex_" << nomeChr << "_5c/" << "chr_" << nomeChr << "/";
      std::string pathGnomadChrDir = streamNomeGnomadChrDir.str();
      std::stringstream streamNomeGnomadChrIndex;
      streamNomeGnomadChrIndex << pathGnomadChrDir << "chr_" << nomeChr << ".txt";
      std::string pathGnomadChrIndex = streamNomeGnomadChrIndex.str();
      std::vector<std::string> vSubfileNames;
      std::vector<int> vSubfileStarts;
      std::vector<int> vSubfileStops;
      std::vector<std::vector<int>> vSubfilePosizioniVector;
      gnomadIndex(pathGnomadChrIndex,
                  vSubfileNames,
                  vSubfileStarts,
                  vSubfileStops,
                  vSubfilePosizioniVector
                );
      std::vector<std::string> vGnomadSubfilePaths;
      srand((unsigned)time(NULL)); //seeds the pseudo random number generator that rand() uses (http://www.cplusplus.com/forum/beginner/29699/)
      int size0 = 10;
      std::vector<int> v0;
      populateVector(v0, size0);

      //the vector with the file names is converted in file paths and then opened and line counted for each file
       std::vector<std::string> vSubfileNames2;
       for (auto si : v0) vSubfileNames2.push_back(vSubfileNames[si]);
       for ( int subCount = 0; subCount < vSubfileNames2.size(); subCount++ ) {
        std::stringstream streamNomeSubfileGnomad;
        streamNomeSubfileGnomad << pathGnomadChrDir << vSubfileNames2[subCount];
        std::string pathGnomadSubfile = streamNomeSubfileGnomad.str();
        gnomadSubfileAnalysis(pathGnomadSubfile);
      }

}




void gnomadSubfileAnalysis( std::string &nomeFile ) {
  size_t length;
  auto f = map_file(nomeFile.c_str(), length);
  auto l = f + length;
  std::vector<int> v0;
  for (int i=0; i<length; i++) if (f[i] == '\n') v0.push_back(i);
  std::cout << "subfile: " << nomeFile << ", has: " << v0.size() << " rows in: " << length << " bytes." << '\n';
}

void  gnomadIndex( std::string &nomeFileIndex,
                    std::vector<std::string> &vSubfileNames,
                    std::vector<int> &vSubfileStarts,
                    std::vector<int> &vSubfileStops,
                    std::vector<std::vector<int>> &vSubfilePosizioniVector
                  ) {
  size_t length;
  auto f = map_file(nomeFileIndex.c_str(), length);
  auto l = f + length;

  std::vector<int> v0;

  v0.push_back(0); 
  for (int i=0; i<length; i++) {
    if (f[i] == '\n') v0.push_back(i+1);
  }
  v0.pop_back();
  for (int nl = 0; nl < v0.size(); nl++) {
    int ncol = 0;
    std::vector<char> vSubfile;
    std::vector<char> vSubStart;
    std::vector<char> vSubStop;
    std::vector<char> vSubPos;
    std::vector<int> vSubfilePosVector;

    for( int start=v0[nl]; start<v0[nl+1]; start++  ) {
      if (f[start] == ',') ncol++;

      if (ncol == 0) {
        if ( f[start] != ',' ) {
          vSubfile.push_back(f[start]);
        }
      }

      if (ncol == 1) {
        if ( f[start] != ',' ) {
          vSubStart.push_back(f[start]);
        }
      }

      if (ncol == 2) {
        if ( f[start] != ',' ) {
          vSubStop.push_back(f[start]);
        }
      }

      if (ncol == 3) {
        if ( f[start] != ',' ) {
          if ( f[start] != ':' ) {
            vSubPos.push_back(f[start]);
          }
          if ( f[start] == ':' || f[start] == '\n' ) {

              std::string subfilePosValue ( vSubPos.begin(), vSubPos.end() );
              vSubPos.clear();

              vSubfilePosVector.push_back( stoi(subfilePosValue) );
              subfilePosValue.erase();
            }
          }
        }
      }

  std::string subFileValue ( vSubfile.begin(), vSubfile.end() );
  vSubfile.clear();
  std::string subfileStartValue ( vSubStart.begin(), vSubStart.end() );
  vSubStart.clear();
  std::string subfileStopValue ( vSubStop.begin(), vSubStop.end() );
  vSubStop.clear();

  vSubfileNames.push_back( subFileValue );
  vSubfileStarts.push_back( stoi( subfileStartValue ) );
  vSubfileStops.push_back( stoi(subfileStopValue) );
  vSubfilePosizioniVector.push_back( vSubfilePosVector );
  }
}

void handle_error(const char* msg) {
    perror(msg);
    exit(255);
}

const char* map_file(const char* fname, size_t& length) {

    int fd = open(fname, O_RDONLY);

    if (fd == -1)
        handle_error("open");

    struct stat sb;

    if (fstat(fd, &sb) == -1)
        handle_error("fstat");

    length = sb.st_size;

    const char* addr = static_cast<const char*>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0u));
    if (addr == MAP_FAILED)
        handle_error("mmap");

    return addr;
}

void populateVector( std::vector<int> &vec, int n ) {
  for( int i = 0 ; i < n ; ++i ) vec.push_back( 0 + rand() % (3000 - 1 + 1)); //gli ultimi due num sono upper e lower range limits
  sort( vec.begin(), vec.end() );
}

int generateRandInt( int l0, int u0 ) {
  int n0 = l0 + rand() % (u0 - l0 + 1);
  return n0;
}

Как и предполагалось, я тогда попробовал с CIN (v1) , здесь код:

#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <vector>
#include <sstream>


void read_file_cin( std::string &nomeFile );
void read_gnomad_index_cin( std::string &nomeFile, char &separator, std::vector<std::string> &vectorName );
void populateVector( std::vector<int> &vec, int n );
int generateRandInt( int l0, int u0 );
std::vector<int> sovrapposizioniVectorsInt( std::vector<int> &v0, std::vector<int> &v1 );

int main() {

  std::string pathGnomadChrIndex = "/Volumes/enrico/gnomad/exomes/splitted_5c/ex_1_5c/chr_1/chr_1.txt";
  char separator = ',';
  std::vector<std::string> vSubfileNames;

  read_gnomad_index_cin(pathGnomadChrIndex, separator, vSubfileNames);

  srand((unsigned)time(NULL)); //seeds the pseudo random number generator that rand() uses (http://www.cplusplus.com/forum/beginner/29699/)
  int size0 = 10;
  std::vector<int> v0;
  populateVector(v0, size0);

   std::vector<std::string> vSubfileNames2;
   for (auto si : v0) vSubfileNames2.push_back(vSubfileNames[si]);

   std::string gnomadSplitDir = "/Volumes/enrico/gnomad/exomes/splitted_5c/ex_1_5c/chr_1/";
   for ( auto vi : vSubfileNames2 ) {
     std::cout << vi << '\n';
     std::stringstream streamNomeGnomadChrDir;
     streamNomeGnomadChrDir << gnomadSplitDir << vi;
     std::string pathSubfile = streamNomeGnomadChrDir.str();
     read_file_cin( pathSubfile );
   }
}

void first_column_cin( char &separator, std::vector<std::string> &vectorName) {
    std::string line;
    int lineCount = 0;
    while(std::getline(std::cin, line)) {
      std::string filename;
      std::istringstream iss(line); 
      getline(iss, filename, separator); 
      vectorName.push_back(filename);
      lineCount++;
    }
}

void read_gnomad_index_cin( std::string &nomeFile, char &separator, std::vector<std::string> &vectorName ) {
    std::ifstream in(nomeFile.c_str());
    std::streambuf *cinbuf = std::cin.rdbuf(); 
    std::cin.rdbuf(in.rdbuf());

    first_column_cin( separator, vectorName );

    std::cin.rdbuf(cinbuf); 
}

void file_countline_cin() {
    std::string line;
    int lineCount = 0;
    while(std::getline(std::cin, line)) lineCount++;
    std::cout << "file has: " << lineCount << " rows." << '\n';
}
void read_file_cin( std::string &nomeFile ) {
    std::ifstream in(nomeFile.c_str());
    std::streambuf *cinbuf = std::cin.rdbuf(); //save old buf
    std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!
    file_countline_cin(); //call function
    std::cin.rdbuf(cinbuf);   //reset to standard input again
}

void populateVector( std::vector<int> &vec, int n ) {
  for( int i = 0 ; i < n ; ++i ) vec.push_back( 0 + rand() % (3000 - 1 + 1)); //gli ultimi due num sono upper e lower range limits
  sort( vec.begin(), vec.end() );
}

int generateRandInt( int l0, int u0 ) {
  int n0 = l0 + rand() % (u0 - l0 + 1);
  return n0;
}

Затем я попытался ускорить CIN (https://www.geeksforgeeks.org/fast-io-for-competitive-programming/) с:

std::ios_base::sync_with_stdio(false);
std::cin.tie(NULL);

здесь CIN.SPEED (v2) версия:

void read_file_cin( std::string &nomeFile );
void read_gnomad_index_cin( std::string &nomeFile, char &separator, std::vector<std::string> &vectorName );


void populateVector( std::vector<int> &vec, int n );
int generateRandInt( int l0, int u0 );

std::vector<int> sovrapposizioniVectorsInt( std::vector<int> &v0, std::vector<int> &v1 );

int main() {

  std::string pathGnomadChrIndex = "/Volumes/enrico/gnomad/exomes/splitted_5c/ex_1_5c/chr_1/chr_1.txt";
  char separator = ',';
  std::vector<std::string> vSubfileNames;

  read_gnomad_index_cin(pathGnomadChrIndex, separator, vSubfileNames);

  srand((unsigned)time(NULL));
  int size0 = 10;
  std::vector<int> v0;
  populateVector(v0, size0);

   std::vector<std::string> vSubfileNames2;
   for (auto si : v0) vSubfileNames2.push_back(vSubfileNames[si]);

   std::string gnomadSplitDir = "/Volumes/enrico/gnomad/exomes/splitted_5c/ex_1_5c/chr_1/";
   for ( auto vi : vSubfileNames2 ) {
     std::cout << vi << '\n';
     std::stringstream streamNomeGnomadChrDir;
     streamNomeGnomadChrDir << gnomadSplitDir << vi;
     std::string pathSubfile = streamNomeGnomadChrDir.str();
     read_file_cin( pathSubfile );
   }
}

void first_column_cin( char &separator, std::vector<std::string> &vectorName) {
  /* SPEEDUP */
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(NULL);
  /* SPEEDUP */
  std::string line;
    int lineCount = 0;
    while(std::getline(std::cin, line)) {
      std::string filename;
      std::istringstream iss(line); // string stream
      getline(iss, filename, separator); // read first part up to comma, ignore the comma
      vectorName.push_back(filename);
      lineCount++;
    }
}

void read_gnomad_index_cin( std::string &nomeFile, char &separator, std::vector<std::string> &vectorName ) {
  /* SPEEDUP */
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(NULL);
  /* SPEEDUP */
    std::ifstream in(nomeFile.c_str());
    std::streambuf *cinbuf = std::cin.rdbuf(); //save old buf
    std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!

    first_column_cin( separator, vectorName ); //call function

    std::cin.rdbuf(cinbuf);   //reset to standard input again
}

void file_countline_cin() {
  /* SPEEDUP */
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(NULL);
  /* SPEEDUP */
    std::string line;
    int lineCount = 0;
    while(std::getline(std::cin, line)) lineCount++;
    std::cout << "file has: " << lineCount << " rows." << '\n';
}


void read_file_cin( std::string &nomeFile ) {
  /* SPEEDUP */
  std::ios_base::sync_with_stdio(false);
  std::cin.tie(NULL);
  /* SPEEDUP */
    std::ifstream in(nomeFile.c_str());
    std::streambuf *cinbuf = std::cin.rdbuf(); //save old buf
    std::cin.rdbuf(in.rdbuf()); //redirect std::cin to in.txt!

    file_countline_cin(); //call function
    std::cin.rdbuf(cinbuf);   //reset to standard input again
}

Затем я попытался с версией mmap, в которой munmapped () и close () файл, который выталкивал все содержимое файла в векторе, а затем возвращал вектор для анализа содержимого файла (просто подсчитывая новую строку в этом тесте), пока оно было munmap. и закрытие карты и файла.

Здесь MMAP.VECTOR (v3):

const char* map_file(const char* fname, size_t& length);

void mmap_file( std::string &filename, std::vector<char> &vFile);

void  gnomadIndex( std::string &nomeFileIndex,
                    std::vector<std::string> &vSubfileNames,
                    std::vector<int> &vSubfileStarts,
                    std::vector<int> &vSubfileStops,
                    std::vector<std::vector<int>> &vSubfilePosizioniVector
                  );
void gnomadSubfileAnalysis( std::string &nomeFile );
void populateVector( std::vector<int> &vec, int n );
int generateRandInt( int l0, int u0 );

int main() {

      std::string gnomadSplitDir = "/Volumes/enrico/gnomad/exomes/splitted_5c/";
      std::string nomeChr = "1";

      std::stringstream streamNomeGnomadChrDir;
      streamNomeGnomadChrDir << gnomadSplitDir << "ex_" << nomeChr << "_5c/" << "chr_" << nomeChr << "/";
      std::string pathGnomadChrDir = streamNomeGnomadChrDir.str();
      std::stringstream streamNomeGnomadChrIndex;
      streamNomeGnomadChrIndex << pathGnomadChrDir << "chr_" << nomeChr << ".txt";
      std::string pathGnomadChrIndex = streamNomeGnomadChrIndex.str();

      std::vector<std::string> vSubfileNames;
      std::vector<int> vSubfileStarts;
      std::vector<int> vSubfileStops;
      std::vector<std::vector<int>> vSubfilePosizioniVector;

      gnomadIndex(pathGnomadChrIndex,
                  vSubfileNames,
                  vSubfileStarts,
                  vSubfileStops,
                  vSubfilePosizioniVector
                );

      std::vector<std::string> vGnomadSubfilePaths;


     srand((unsigned)time(NULL));
      int size0 = 10;
      std::vector<int> v0;
      populateVector(v0, size0);

       std::vector<std::string> vSubfileNames2;
       for (auto si : v0) vSubfileNames2.push_back(vSubfileNames[si]);

      for ( int subCount = 0; subCount < vSubfileNames2.size(); subCount++ ) {

        std::stringstream streamNomeSubfileGnomad;
        streamNomeSubfileGnomad << pathGnomadChrDir << vSubfileNames2[subCount];
        std::string pathGnomadSubfile = streamNomeSubfileGnomad.str();

        gnomadSubfileAnalysis(pathGnomadSubfile);
      }

}

void gnomadSubfileAnalysis( std::string &nomeFile ) {

  std::vector<char> f;
  mmap_file(nomeFile, f);

  std::vector<int> v0;

  for (int i=0; i<f.size(); i++) if (f[i] == '\n') v0.push_back(i);

  std::cout << "subfile: " << nomeFile << ", has: " << v0.size() << " rows in: " << f.size() << " bytes." << '\n';
}

void  gnomadIndex( std::string &nomeFileIndex,
                    std::vector<std::string> &vSubfileNames,
                    std::vector<int> &vSubfileStarts,
                    std::vector<int> &vSubfileStops,
                    std::vector<std::vector<int>> &vSubfilePosizioniVector
                  ) {


  std::vector<char> f;
  mmap_file(nomeFileIndex, f);
  std::vector<int> v0;

  v0.push_back(0); //la prima riga mi serve qui
  for (int i=0; i<f.size(); i++) {
    if (f[i] == '\n') v0.push_back(i+1);
  }
  v0.pop_back();

  for (int nl = 0; nl < v0.size(); nl++) {

    int ncol = 0;

    std::vector<char> vSubfile;
    std::vector<char> vSubStart;
    std::vector<char> vSubStop;
    std::vector<char> vSubPos;
    std::vector<int> vSubfilePosVector;

    for( int start=v0[nl]; start<v0[nl+1]; start++  ) {

      if (f[start] == ',') ncol++;

      if (ncol == 0) {
        if ( f[start] != ',' ) {
          vSubfile.push_back(f[start]);
        }
      }

      if (ncol == 1) {
        if ( f[start] != ',' ) {
          vSubStart.push_back(f[start]);
        }
      }

      if (ncol == 2) {
        if ( f[start] != ',' ) {
          vSubStop.push_back(f[start]);
        }
      }

      if (ncol == 3) {
        if ( f[start] != ',' ) {
          if ( f[start] != ':' ) {
            vSubPos.push_back(f[start]);
          }
          if ( f[start] == ':' || f[start] == '\n' ) {

              std::string subfilePosValue ( vSubPos.begin(), vSubPos.end() );
              vSubPos.clear();

              vSubfilePosVector.push_back( stoi(subfilePosValue) );
              subfilePosValue.erase();
            }
          }
        }
      }

  std::string subFileValue ( vSubfile.begin(), vSubfile.end() );
  vSubfile.clear();
  std::string subfileStartValue ( vSubStart.begin(), vSubStart.end() );
  vSubStart.clear();
  std::string subfileStopValue ( vSubStop.begin(), vSubStop.end() );
  vSubStop.clear();

  vSubfileNames.push_back( subFileValue );
  vSubfileStarts.push_back( stoi( subfileStartValue ) );
  vSubfileStops.push_back( stoi(subfileStopValue) );
  vSubfilePosizioniVector.push_back( vSubfilePosVector );
  }
}


void handle_error(const char* msg) {
    perror(msg);
    exit(255);
}

const char* map_file(const char* fname, size_t& length) {

    int fd = open(fname, O_RDONLY);

    if (fd == -1)
        handle_error("open");

    struct stat sb;

    if (fstat(fd, &sb) == -1)
        handle_error("fstat");

    length = sb.st_size;

    const char* addr = static_cast<const char*>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0u));
    if (addr == MAP_FAILED)
        handle_error("mmap");

    return addr;
}



void populateVector( std::vector<int> &vec, int n ) {
  for( int i = 0 ; i < n ; ++i ) vec.push_back( 0 + rand() % (3000 - 1 + 1)); //gli ultimi due num sono upper e lower range limits
  sort( vec.begin(), vec.end() );
}

int generateRandInt( int l0, int u0 ) {
  int n0 = l0 + rand() % (u0 - l0 + 1);
  return n0;
}


size_t getFilesize(const char* filename) {
    struct stat st;
    stat(filename, &st);
    return st.st_size;
}


void mmap_file( std::string &filename, std::vector<char> &vFile) {
    size_t filesize = getFilesize(filename.c_str());
    int fd = open(filename.c_str(), O_RDONLY, 0);
    assert(fd != -1);
    void* mmappedData = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
    assert(mmappedData != MAP_FAILED);

    const char* f = static_cast<const char*>(mmappedData);

    for ( int i = 0; i < filesize; i++ ) vFile.push_back(f[i]);

    int rc = munmap(mmappedData, filesize);
    assert(rc == 0);
    close(fd);

}

Но я сразу увидел, что это было медленнее, я думал, что это может быть связано с дальнейшим переходом к заполнению вектора, поэтому я попробовал версию, которая считала символы новой строки, когда mmap был открыт, а затем закрыл ее.

MMAP. ЗАКРЫТЬ (v4) :

 const char* map_file(const char* fname, size_t& length);

void mmap_file( std::string &filename, std::vector<char> &vFile);
int mmap_file_nlines( std::string &filename );
void  gnomadIndex( std::string &nomeFileIndex,
                    std::vector<std::string> &vSubfileNames,
                    std::vector<int> &vSubfileStarts,
                    std::vector<int> &vSubfileStops,
                    std::vector<std::vector<int>> &vSubfilePosizioniVector
                  );
void gnomadSubfileAnalysis( std::string &nomeFile );
void populateVector( std::vector<int> &vec, int n );
int generateRandInt( int l0, int u0 );

int main() {

      std::string gnomadSplitDir = "/Volumes/enrico/gnomad/exomes/splitted_5c_text/";
      std::string nomeChr = "1";

      std::stringstream streamNomeGnomadChrDir;
      streamNomeGnomadChrDir << gnomadSplitDir << "chr_" << nomeChr << "/";
      std::string pathGnomadChrDir = streamNomeGnomadChrDir.str();
      std::stringstream streamNomeGnomadChrIndex;
      streamNomeGnomadChrIndex << pathGnomadChrDir << "chr_" << nomeChr << ".txt";
      std::string pathGnomadChrIndex = streamNomeGnomadChrIndex.str();

      std::vector<std::string> vSubfileNames;
      std::vector<int> vSubfileStarts;
      std::vector<int> vSubfileStops;
      std::vector<std::vector<int>> vSubfilePosizioniVector;

      gnomadIndex(pathGnomadChrIndex,
                  vSubfileNames,
                  vSubfileStarts,
                  vSubfileStops,
                  vSubfilePosizioniVector
                );

      std::vector<std::string> vGnomadSubfilePaths;


      srand((unsigned)time(NULL));
      int size0 = 10;
      std::vector<int> v0;
      populateVector(v0, size0);
       std::vector<std::string> vSubfileNames2;
       for (auto si : v0) vSubfileNames2.push_back(vSubfileNames[si]);

      for ( int subCount = 0; subCount < vSubfileNames2.size(); subCount++ ) {
        std::stringstream streamNomeSubfileGnomad;
        streamNomeSubfileGnomad << pathGnomadChrDir << vSubfileNames2[subCount];
        std::string pathGnomadSubfile = streamNomeSubfileGnomad.str();
        gnomadSubfileAnalysis(pathGnomadSubfile);
      }

}

void gnomadSubfileAnalysis( std::string &nomeFile ) {
  int nLinee = mmap_file_nlines(nomeFile);

  std::cout << "subfile: " << nomeFile << ", has: " << nLinee << " rows" << '\n';
}

void  gnomadIndex( std::string &nomeFileIndex,
                    std::vector<std::string> &vSubfileNames,
                    std::vector<int> &vSubfileStarts,
                    std::vector<int> &vSubfileStops,
                    std::vector<std::vector<int>> &vSubfilePosizioniVector
                  ) {

  size_t length;
  auto f = map_file(nomeFileIndex.c_str(), length);
  auto l = f + length;
  std::vector<int> v0;
  v0.push_back(0); //la prima riga mi serve qui
  for (int i=0; i<length; i++) {
    if (f[i] == '\n') v0.push_back(i+1);
  }
  v0.pop_back();

  for (int nl = 0; nl < v0.size(); nl++) {

    int ncol = 0;
    std::vector<char> vSubfile;
    std::vector<char> vSubStart;
    std::vector<char> vSubStop;
    std::vector<char> vSubPos;
    std::vector<int> vSubfilePosVector;

    for( int start=v0[nl]; start<v0[nl+1]; start++  ) {
      if (f[start] == ',') ncol++;
      if (ncol == 0) {
        if ( f[start] != ',' ) {
          vSubfile.push_back(f[start]);
        }
      }
      if (ncol == 1) {
        if ( f[start] != ',' ) {
          vSubStart.push_back(f[start]);
        }
      }
      if (ncol == 2) {
        if ( f[start] != ',' ) {
          vSubStop.push_back(f[start]);
        }
      }
      if (ncol == 3) {
        if ( f[start] != ',' ) {
          if ( f[start] != ':' ) {
            vSubPos.push_back(f[start]);
          }
          if ( f[start] == ':' || f[start] == '\n' ) {
              std::string subfilePosValue ( vSubPos.begin(), vSubPos.end() );
              vSubPos.clear();
              vSubfilePosVector.push_back( stoi(subfilePosValue) );
              subfilePosValue.erase();
            }
          }
        }
      }

  std::string subFileValue ( vSubfile.begin(), vSubfile.end() );
  vSubfile.clear();
  std::string subfileStartValue ( vSubStart.begin(), vSubStart.end() );
  vSubStart.clear();
  std::string subfileStopValue ( vSubStop.begin(), vSubStop.end() );
  vSubStop.clear();
  vSubfileNames.push_back( subFileValue );
  vSubfileStarts.push_back( stoi( subfileStartValue ) );
  vSubfileStops.push_back( stoi(subfileStopValue) );
  vSubfilePosizioniVector.push_back( vSubfilePosVector );
  }
}

void handle_error(const char* msg) {
    perror(msg);
    exit(255);
}
const char* map_file(const char* fname, size_t& length) {

    int fd = open(fname, O_RDONLY);
    if (fd == -1)
        handle_error("open");
    struct stat sb;
    if (fstat(fd, &sb) == -1)
        handle_error("fstat");
    length = sb.st_size;

    const char* addr = static_cast<const char*>(mmap(NULL, length, PROT_READ, MAP_PRIVATE, fd, 0u));
    if (addr == MAP_FAILED)
        handle_error("mmap");
    return addr;
}

void populateVector( std::vector<int> &vec, int n ) {
  for( int i = 0 ; i < n ; ++i ) vec.push_back( 0 + rand() % (3000 - 1 + 1)); //gli ultimi due num sono upper e lower range limits
  sort( vec.begin(), vec.end() );
}

int generateRandInt( int l0, int u0 ) {
  int n0 = l0 + rand() % (u0 - l0 + 1);
  return n0;
}

size_t getFilesize(const char* filename) {
    struct stat st;
    stat(filename, &st);
    return st.st_size;
}

void mmap_file( std::string &filename, std::vector<char> &vFile) {
    size_t filesize = getFilesize(filename.c_str());
    int fd = open(filename.c_str(), O_RDONLY, 0);
    assert(fd != -1);
    void* mmappedData = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
    assert(mmappedData != MAP_FAILED);

    const char* f = static_cast<const char*>(mmappedData);

    for ( int i = 0; i < filesize; i++ ) vFile.push_back(f[i]);
    int rc = munmap(mmappedData, filesize);
    assert(rc == 0);
    close(fd);
}

int mmap_file_nlines( std::string &filename ) {
    size_t filesize = getFilesize(filename.c_str());
    int fd = open(filename.c_str(), O_RDONLY, 0);
    assert(fd != -1);
    void* mmappedData = mmap(NULL, filesize, PROT_READ, MAP_PRIVATE, fd, 0);
    assert(mmappedData != MAP_FAILED);

    const char* f = static_cast<const char*>(mmappedData);
    int lineCount =0 ;
    for ( int i = 0; i < filesize; i++ ) if( f[i] == '\n' ) lineCount++;
    int rc = munmap(mmappedData, filesize);
    assert(rc == 0);
    close(fd);

    return lineCount;

}

Здесь среднее значение в секундах для 1000 попыток при каждом подходе:

          cin 0.983380
    cin.speed 0.989011
   mmap.close 2.863860
    mmap.open 0.915395
  mmap.vector 4.683976

Я был несколько удивлен, что «ускорение» для CIN ничего не изменило (может быть, я что-то не так понял) и что закрытие файла было таким трудоемким для mmap!

Вот график результатов.

enter image description here

Любые комментарии большего количества экспертов действительно приветствуются!

PS: моя машина представляет собой iMac (Retina 5K, 27 дюймов, конец 2014 г.), Intel Core i7 4 ГГц, 16 ГБ, 1600 МГц DDR3

...