C语言程序作为Python子进程运行时更快

11

我在C语言中编写了一个多线程的归并排序程序,并编写了一个基准测试程序,可用0、1、2或4个线程进行测试。我还编写了一个Python程序来执行多个测试并汇总结果。

奇怪的是,当我运行Python程序时,测试时间总是比直接在shell中运行测试程序快一半左右。

例如,当我仅使用4百万个整数运行测试程序(最后两个参数是生成整数的种子和模数):

$ ./mergetest 4000000 4194819 140810581084
0 threads:  1.483485s wall;  1.476092s user;  0.004001s sys
1 threads:  1.489206s wall;  1.488093s user;  0.000000s sys
2 threads:  0.854119s wall;  1.608100s user;  0.008000s sys
4 threads:  0.673286s wall;  2.224139s user;  0.024002s sys

使用 Python 脚本:

$ ./mergedata.py 1 4000000
Average runtime for 1 runs with 4000000 items each:
0 threads:   0.677512s wall;   0.664041s user;   0.016001s sys
1 threads:   0.709118s wall;   0.704044s user;   0.004001s sys
2 threads:   0.414058s wall;   0.752047s user;   0.028001s sys
4 threads:   0.373708s wall;    1.24008s user;   0.024002s sys
无论我排序多少次,或者运行多少次,都会出现这种情况。Python程序使用subprocess模块调用测试器,然后解析和聚合输出。有什么想法为什么会发生这种情况吗?Python是否在优化执行?还是当我直接运行时有一些我不知道的东西在减慢它的速度?
代码:https://gist.github.com/2650009

10
可以给我们展示一下 Python 代码吗? - NPE
3
...还有C代码。或者至少提供指向Github或类似网站的代码指针。 - James Youngman
7
是不是因为从 shell 执行程序导致程序花费过多的时间打印到控制台?尝试将 stdout 重定向到 /dev/null,看看是否会改变情况。 - Aidan Steele
2
找到了。当我将sys.maxint作为模数传递时,C将其视为有符号的,即-1,使得生成的每个数字都变为0。因此,我猜比较和移动一堆0大约需要实际数据的一半时间。 - scry
1
真糟糕,你不能再花点时间吗?我刚刚也发现了这个问题。Python在64位系统上有64位的int,而C语言的int仍然是32位。 - Daniel Fischer
显示剩余2条评论
2个回答

2
原来我在生成随机数的模数中传递了sys.maxint给子进程。C截断了64位整数并将其解释为有符号整数,即two's complement中的-1,因此每个随机数都被该数字取模,并变为0。因此,对于所有相同的值进行排序似乎需要的时间仅为随机数据的一半。

0
将其包装在一个shell脚本中可能会产生相同的效果。如果是这样,那么它就是控制台操作。

在bash脚本中包装没有效果 - 仍然比Python慢两倍。哪些控制台操作会对性能产生如此大的影响? - scry
输出缓冲。我认为你需要发布Python脚本,以便任何人都有机会解决这个问题。 - Peter Moore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接