在C中读取1 GB二进制文件需要太长时间

时间:2016-05-16 13:08:57

标签: c file-handling

我正在阅读一个文件,里面有元组的数量" n_tups"单个元组的长度或其长度" d"是输入。对于二维数组" tuple"我已按如下方式分配内存。

当我运行代码时,我的计算机挂起,我不知道为什么。

if((fpp = fopen("in2.bin", "rb"))==NULL)
   printf("file in2.bin doesn't exist!");
else
{
 int **tuple;
 unsigned long i;

 tuple = malloc(n_tups * sizeof(int *));

 if(tuple == NULL)
   {
      fprintf(stderr, "out of memory\n");
      return;
   }
 for(i=0;i<n_tups;i++){
        tuple[i]=malloc(d * sizeof(int));
        if(tuple[i] == NULL)
        {
           fprintf(stderr, "out of memory\n");
           return;
         }  
  }

 fseek( fpp , 0 , SEEK_SET );
 printf("reading step");
 for(i=0;i<n_tups;i++){
         fread(&tuple[i],4,d,fpp);
         fread(&score[i],8,1,fpp);
    }

 fclose(fpp);
 }

我试图检查程序是否到达&#34;阅读步骤&#34;它没有。原来忙于分配内存! 我通过d = 3 n_tups = 85013600,我的电脑有4 GB的RAM。

1 个答案:

答案 0 :(得分:4)

代码本身存在两个性能问题。

  • 即使所有维度都相同,您也会不必要地使用指向指针的查找表。使用2D数组会好得多,因此所有数据都分配在相邻的内存中。这样,CPU不必每次读取堆都会挖掘RAM,而是可以利用数据缓存内存。

    像这样:

    int (*tuple)[d] = malloc( sizeof(int[n_tups][d]) );
    ...
    free(tuple);
    
  • 每次拨打fread都会很费劲。尝试每次调用尽可能读取大块。在你的情况下,什么是最佳的,我不知道 - 它是系统依赖的。但是将其称为小块数据将无效。特别是因为正确编写的程序将始终检查每个fread调用的结果。

    理想情况下,假设您遵循我之前关于使用2D阵列的建议,您只需要这样做:

    result = fread(tuple, sizeof(int[n_tups][d]), 1, fpp);
    

    但是,该文件似乎包含您希望存储在其他位置的无关数据。考虑使用单个结构数组替换两个int数组,这样您每次都可以读取更长的内存块。 (但是,请注意构造填充。)

    请注意,从磁盘读取非常大的数据块可能非常耗时,因此请考虑从其他线程而不是主(GUI?)线程执行此操作。