如果比较不应该以这种方式工作,我深表歉意。我是编程新手,只是好奇为什么会这样。
我有一个包含单词嵌入(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 filen");
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("%dn", count);
clock_t end = clock();
double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
printf("%fn", time_spent);
这需要 11.283060 秒。
蟒:
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
的效率也就不足为奇了