我正在运行这两个代码。它们都执行相同的数学过程(最多计算序列值),并且按预期方式产生相同的输出。
但是由于某些原因,PyPy代码的运行速度明显快于C代码。
我无法弄清楚为什么会这样,因为我期望C代码运行得更快。
如果有人能帮助我澄清一下,我将不胜感激(也许还有更好的方式编写C代码?)
C代码:
#include <stdio.h>
#include <math.h>
int main()
{
double Sum = 0.0;
long n;
for(n = 2; n < 1000000000; n = n + 1) {
double Sign;
Sign = pow(-1.0, n % 2);
double N;
N = (double) n;
double Sqrt;
Sqrt = sqrt(N);
double InvSqrt;
InvSqrt = 1.0 / Sqrt;
double Ln;
Ln = log(N);
double LnSq;
LnSq = pow(Ln, 2.0);
double Term;
Term = Sign * InvSqrt * LnSq;
Sum = Sum + Term;
}
double Coeff;
Coeff = Sum / 2.0;
printf("%0.14f \n", Coeff);
return 0;
}
PyPy代码(更快的Python实现):
from math import log, sqrt
Sum = 0
for n in range(2, 1000000000):
Sum += ((-1)**(n % 2) * (log(n))**2) / sqrt(n)
print(Sum / 2)
答案 0 :(得分:4)
这毫不奇怪,PyPy
默认情况下会执行许多运行时优化,而C
编译器默认情况下不会执行任何优化。戴夫·比兹利(Dave Beazley)的2012 PyCon Keynote非常清楚地介绍了这一点,并提供了对此发生原因的深入解释。
根据引用的内容,C
在使用optimization level PyPy
或2
进行编译时应超过3
(您可以观看有关从here开始的cpython
,pypy
和C
中的斐波那契生成。
答案 1 :(得分:2)
除了编译器的优化级别之外,您还可以改善代码:
int main()
{
double Sum = 0.0;
long n;
for(n = 2; n < 1000000000; ++n)
{
double N = n; // cast is implicit, only for code readability, no effect on runtime!
double Sqrt = sqrt(N);
//double InvSqrt; // spare that:
//InvSqrt = 1.0/Sqrt; // you spare this division with!
double Ln = log(N);
double LnSq;
//LnSq = pow(Ln,2.0);
LnSq = Ln*Ln; // more efficient
double Term;
//Term = Sign * InvSqrt * LnSq;
Term = LnSq / Sqrt;
if(n % 2)
Term = -Term; // just negating, no multiplication
// (IEEE provided: just one bit inverted)
Sum = Sum + Term;
}
// ...
现在,我们可以进一步简化代码:
int main()
{
double Sum = 0.0;
for(long n = 2; n < 1000000000; ++n)
// ^^^^ possible since C99, better scope, no runtime effect
{
double N = n;
double Ln = log(N);
double Term = Ln * Ln / sqrt(N);
if(n % 2)
Sum -= Term;
else
Sum += Term;
}
// ...