Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python实现比C更快_Python_C_Linux_File_Mmap - Fatal编程技术网

Python实现比C更快

Python实现比C更快,python,c,linux,file,mmap,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.v

如果比较不应该这样做,我道歉。我是编程新手,只是好奇为什么会这样

我有一个包含单词嵌入(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);
这需要3.063306543997154秒


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

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

for line in file:
    count += 1

将在一个调用
fgets
的小函数上循环结束。我敢打赌,一个使用
fgets
的朴素C程序将比Python等效程序稍微快一点,因为它将节省所有Python开销。但是我毫不奇怪在C中使用
mmap
比在Python中使用
fgets
效率低

如何计算行数?它不是将每个字符与换行符进行比较吗?如果是这样,它与我在C中所做的有什么不同?因为您只读取了一次文件,所以使用
mmap()
可能比使用
fgets()
或POSIX
getline()
读取并计数行效率低。您可能对此感兴趣。我高度怀疑您没有在C程序中启用优化功能。我用一个1G大小的文件在我的机器上测试了你的代码,没有优化,C稍微慢一点,而且
time
command显示用户时间很长;对于-O2,C比Python快得多。摘要:在某些情况下,
mmap()
可能会很慢。这就是其中之一。另请参见
mmap()
vs
fgets()
的使用可能会对操作系统的内置文件缓存产生影响。我想,任何一个为单个
fgets()
提供服务的操作系统,只要值一毛钱,都会在这样做的同时麻烦地提前缓存。这将加速下一个
fgets()
。对于
mmap
ed文件,操作系统可能不会麻烦,也不会有不同的缓存策略;以这种方式打开的文件与其说是从当前文件指针操作的函数(如
fgets()
),不如说是随机访问。事实上,在发布的代码中使用
mmap()
的方式可能是使用
mmap()
最糟糕的方式
mmap()
代价高昂-内核不仅要从磁盘复制数据,还必须在进程的地址空间中创建虚拟映射。那不是免费的。只有在数据被多次重用的情况下,支付这种成本才是值得的。使用
mmap()
时,最糟糕的方法是只传递一次文件数据<代码>mmap()如果您正在重用数据,或者如果您想要简单的代码而不真正关心性能,那么代码>mmap()是很好的选择。
for line in file:
    count += 1