Python 实现比 C 快

标签 python c linux file mmap

如果比较不应该以这种方式进行,我深表歉意。我是编程新手,只是很好奇为什么会这样。

我有一个包含词嵌入的大型二进制文件 (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 代码如此低效?

最佳答案

很难说,因为我认为它将在很大程度上依赖于实现。但乍一看,Python 和 C 程序的主要区别在于 C 程序使用 mmap。它是一个非常强大的工具(您在这里并不真正需要它……),因此可能会带来一些开销。由于引用 Python 实现是用 C 编写的,因此循环很可能

for line in file:
    count += 1

将在一个调用 fgets 的小函数上循环结束。我敢打赌,使用 fgets 的简单 C 程序会比 Python 等效程序稍快一些,因为它将节省所有 Python 开销。但是恕我直言,在 C 中使用 mmap 比在 Python 中使用 fgets 效率低也就不足为奇了

关于Python 实现比 C 快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48484240/

相关文章:

Python 或 R! - 为指定的光栅文件绘制直方图

python - 将元组转换为嵌套列表的索引

python - web2py - 显示网格中的对象列表

C套接字客户端重新连接到服务器时收到大量数据

c - Vsnprintf 在我的嵌入式目标上因 NULL 而崩溃

linux - 如何使 Linux 脚本将 "\"理解为 ' ' 以用于路径目的

python - 在 sympy 中集成分段函数时出现错误结果

c - 检索文件指针到原始位置

c - 来自linux shell脚本的函数不在c程序中执行

linux - Bash date 命令无效日期