C中的多线程读取和打印非常大的文件

Multithreading in C to read and print a very large file

我有一个非常大的文件要读取并执行以下操作。

  1. 打开大文件 (>50MB) 并逐行阅读
  2. 执行一些比较操作
  3. 打印比较结果
  4. Return

当我在单线程 C 代码中执行上述序列时,它工作正常,现在我试图通过创建 3 个线程来使用多线程来使其更快(我被授权使用 3 个线程来使这个过程更快) 阅读和比较,但我没有这样做,因为我看到它只是重复了一些比较。

有什么方法可以让我使用 3 个线程读取文件的 3 个不同部分并执行一些操作吗?

请注意,这个答案是一个“技巧”(或者可能是分配是一个技巧?),因为它并没有真正使过程更快。答案假定标准 Linux 计算机具有合理的 (4G+) 内存。

简短回答:在任何半正经的配置中,数据将移动到 OS 缓冲区,问题实际上是 CPU 绑定,而不是 IO 绑定。

长答案:

虽然 50MB 的文件对于人类来说是 'Large',但对于每台现代计算机来说都是 'Small'。实际上,数据将移入 OS 缓冲区,并会留在那里,除非系统需要内存用于其他任务。

给定数据在 (OS) 内存中,问题(初始调用除外)不是 IO 绑定的,而是 CPU 绑定的。对于这个 3 线程 MT 程序将发挥神奇作用。问题变成了如何将工作分散到 3 个文件中。理想情况下,3 个线程会将文件分成 3 个(几乎)相等的块,每个块单独处理。

解决方案是伪代码,实际代码必须处理分割块的行的处理、错误检查等。

FILE *data_fp ;
static int block_size ;

main() {
   data_fp = fopen(...) ;
   int filesize = ftell(fp) ;
   block_size = filesize/6 ;

   for (int i=0 ; i<N_THREADS ; i++ ) {
       start_offset = filefize*((float i)/N_THREADS) ;
       pthread_create(search_start, ... , &start_offset) ;
   }
}

search_start(void *arg) {

   // Extract the offset to start
   long start_offset = * (long *) arg ;
   // Create separate FILE*, with separate position, buffers, etc.
   FILE *local_fp = fdopen(fileno(data_fp), "r") ;

   // Position at the thread specific offset
   fseek(local_fp, start_offset, SEEK_SET) ;

   char buff[256] ;  // max line size
   // Loop until EOF, some exit condition, or block_size characters processed
   for (long p = 0 ; p < block_size && fgets(buff, sizeof(buff), local_fp) ; p += strlen(buff)) {
       // Compare, check, whatever is needed
       ...
       if (need_to_stop) break ;
   } ;
   fclose(local_fp) ;

}

使用 'mmap' 可能会更快。但是,问题要求行处理,鉴于这不是现实生活中的问题,不确定是否值得付出额外的努力。