首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在大的文本列数据文件中读取最快的方法是什么?

在大的文本列数据文件中读取最快的方法是什么?
EN

Stack Overflow用户
提问于 2010-09-23 13:53:39
回答 5查看 5.2K关注 0票数 4

我有一个将近900万行的数据文件(很快就会超过5亿行),我正在寻找最快的方法来读取它。这五个对齐的列由空格填充和分隔,因此我知道在每一行中查找我想要的两个字段的位置。我的Python例程需要45秒:

代码语言:javascript
复制
import sys,time

start = time.time()
filename = 'test.txt'    # space-delimited, aligned columns
trans=[]
numax=0
for line in open(linefile,'r'):
    nu=float(line[-23:-11]); S=float(line[-10:-1])
    if nu>numax: numax=nu
    trans.append((nu,S))
end=time.time()
print len(trans),'transitions read in %.1f secs' % (end-start)
print 'numax =',numax

而我在C中提出的例程是一个更令人愉快的4秒:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define BPL 47
#define FILENAME "test.txt"
#define NTRANS 8858226

int main(void) {
  size_t num;
  unsigned long i;
  char buf[BPL];
  char* sp;
  double *nu, *S;
  double numax;
  FILE *fp;
  time_t start,end;

  nu = (double *)malloc(NTRANS * sizeof(double));
  S = (double *)malloc(NTRANS * sizeof(double));

  start = time(NULL);
  if ((fp=fopen(FILENAME,"rb"))!=NULL) {
    i=0;
    numax=0.;
    do {
      if (i==NTRANS) {break;}
      num = fread(buf, 1, BPL, fp);
      buf[BPL-1]='\0';
      sp = &buf[BPL-10]; S[i] = atof(sp);
      buf[BPL-11]='\0';
      sp = &buf[BPL-23]; nu[i] = atof(sp);
      if (nu[i]>numax) {numax=nu[i];}
      ++i;
    } while (num == BPL);
    fclose(fp);
    end = time(NULL);
    fprintf(stdout, "%d lines read; numax = %12.6f\n", (int)i, numax);
    fprintf(stdout, "that took %.1f secs\n", difftime(end,start));
  } else {
    fprintf(stderr, "Error opening file %s\n", FILENAME);
    free(nu); free(S);
    return EXIT_FAILURE;
  }

  free(nu); free(S);
  return EXIT_SUCCESS;
  }

Fortran、C++和Java中的解决方案需要一定的时间(27秒、20秒、8秒)。我的问题是:我是否犯下了任何令人震惊的错误(特别是C-code)?还有任何方法来加速Python例程吗?我很快意识到,将数据存储在元组数组中比为每个条目实例化类更好。

EN

回答 5

Stack Overflow用户

发布于 2010-09-23 14:38:37

以下几点:

  1. 你的C例程是作弊;它是与文件大小的提示,并且是预先分配.
  2. 考虑使用array.array('d') ..。S和nu各一张。那就试试预先分配。
  3. Python:将你的例程写成一个函数并调用它--访问函数--局部变量比访问模块-全局变量要快得多。
票数 4
EN

Stack Overflow用户

发布于 2010-09-23 14:05:22

在C实现中,可以尝试将fopen()/fread()/fclose()库函数转换为较低级别的系统调用open()/read()/close().。加速可能来自于这样一个事实:fread()做了大量的缓冲,而read()却没有。

此外,使用更大的块更少地调用read()将减少系统调用的数量,因此在用户空间和内核空间之间的切换将更少。内核在发出read()系统调用(如果从fread()库函数调用它)时所做的事情是从磁盘读取数据,然后将其复制到用户空间。如果您经常在代码中发出系统调用,复制部分就会变得非常昂贵。通过大块阅读,你最终会得到更少的上下文切换和更少的复制。

但是,请记住,read()不一定会返回您想要的确切字节数的块。这就是为什么在可靠和正确的实现中,您必须始终检查read()的返回值。

票数 3
EN

Stack Overflow用户

发布于 2010-09-23 14:22:29

一种可能应用于C、C++和python版本的方法是使用内存映射文件。最有意义的好处是,当数据从一个缓冲区复制到另一个缓冲区时,它可以减少对数据的双重处理。在许多情况下,由于系统调用I/O的次数减少,也有好处。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3779073

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档