Python实现比C

时间:2018-01-28 07:44:19

标签: python c linux file mmap

如果比较不应该以这种方式起作用,我道歉。我是编程新手,只是好奇为什么会这样。

我有一个包含word嵌入(4.5gb)的大型二进制文件。每行都有一个单词,后跟嵌入,由300个浮点值组成。我只是找到总行数。

对于C,我使用mmap:

int fd; 
struct stat sb; 
off_t offset = 0, pa_offset;
size_t length, i;
char *addr;
int count = 0;

fd = open("processed_data/crawl-300d-2M.vec", O_RDONLY);
if(fd == -1){
    handle_error("open");
    exit(1);
}

if(fstat(fd, &sb) < 0){
    handle_error("fstat");
    close(fd);
    exit(1);
}

pa_offset = offset & ~(sysconf(_SC_PAGE_SIZE) - 1);
if(offset >= sb.st_size){
    fprintf(stderr, "offset is past end of file\n");
    exit(EXIT_FAILURE);
}

length = sb.st_size - offset;
addr = mmap(0, (length + offset - pa_offset), PROT_READ, MAP_SHARED, fd, pa_offset);
if (addr == MAP_FAILED) handle_error("mmap");

//Timing only this loop
clock_t begin = clock();
for(i=0;i<length;i++){
    if(*(addr+i) == '\n') count++;
}
printf("%d\n", count);
clock_t end = clock();  
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("%f\n", time_spent);

这需要11.283060秒。

的Python:

file = open('processed_data/crawl-300d-2M.vec', 'r')
count = 0
start_time = timeit.default_timer()
for line in file:
    count += 1
print(count)
elapsed = timeit.default_timer() - start_time
print(elapsed)

这需要3.0633065439997154秒。

没有Python代码读取每个字符以查找新行吗?如果是这样,为什么我的C代码效率低下呢?

1 个答案:

答案 0 :(得分:3)

很难说,因为我认为它将严重依赖于实现。但乍一看,Python和C程序之间的主要区别在于C程序使用mmap。它是一个非常强大的工具(你在这里并不需要......)因此可能带来一些开销。由于参考Python实现是用C语言编写的,因此很可能是循环

for line in file:
    count += 1

将以一个调用fgets的微小函数循环结束。我敢打赌,使用fgets的天真C程序将比Python等效的程序略快,因为它将节省所有Python开销。但是恕我直言,在C中使用mmap的效率低于Python中的fgets