Python的运行速度明显快于C ++?这里似乎有些问题

tjw*_*992 2 c++ python performance

在将其转换为C ++之前,我一直在使用Python进行一些快速原型制作,发现在某些情况下,Python代码的运行速度明显快于C ++代码!

考虑一下用Python和C ++编写的简单循环:


蟒蛇:

import numpy as np
import datetime

N = 16777216
f_s = 8000.0
t_s = 1/f_s

y = np.empty(N)

start = datetime.datetime.now()

for n in range(0,N):
    y[n] = np.sin(2*np.pi*1000*n*t_s) + 0.5*np.sin(2*np.pi*2000*n*t_s + 3*np.pi/4)

stop = datetime.datetime.now()
duration = stop - start

print("duration ", duration.microseconds, " microseconds")
Run Code Online (Sandbox Code Playgroud)

输出:

持续时间842000微秒


C ++:

#include <chrono>
#include <cmath>
#include <iostream>
#include <vector>

int main() {
    int N = 16777216;
    int f_s = 8000;
    double t_s = 1.0 / f_s;

    std::vector<double> x(N);

    auto start = std::chrono::high_resolution_clock::now();

    for (int n = 0; n < N; ++n)
    {
            x[n] = std::sin(2 * M_PI * 1000 * n * t_s) + 0.5 * std::sin(2 * M_PI * 2000 * n * t_s + 3 * M_PI / 4);
    }

    auto stop = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(stop - start);

    std::cout << "duration " << duration.count() << " microseconds." << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出:

持续时间1993000微秒。


Python代码似乎确实要花费大量的启动时间,而C ++代码会立即运行。(也许Python解释器在启动时需要花费很长时间进行一些优化?)但是尽管如此,但一旦Python代码运行,循环本身在Python中的运行速度就会大大提高。

这让我大吃一惊,但我似乎无法弄清楚Python如何如此快地运行此循环。我什至尝试在不同的优化级别上编译C ++代码,以查看编译器是否以某种方式在优化方面做得不好。上面的C ++示例经过编译,g++ -O3以改善优化效果。当没有切入时,我什至尝试g++ -Ofast将运行时间提高到1205000微秒,但仍然比Python循环慢得多!

我已经尝试了Googling,但找不到任何真正的解释……这怎么可能发生?如何从C ++循环中获得更好的性能?我希望我可以和Python循环一样快,甚至更快。


我在跑步 Python 3.7.2

C ++的例子是使用编译g++.exe (MinGW.org GCC-6.3.0-1) 6.3.0-O3编译器开关,以提高优化。

我还尝试在Linux环境中编译C ++代码,g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36)结果相似。

big*_*_29 12

您使用的microseconds组件不timedelta正确。它仅为您提供时间测量的亚秒级部分,而不是总经过的微秒级。此代码突出了您的错误

from datetime import datetime, timedelta

start = datetime(2019, 1, 1, 12, 0, 0, 0 )
end   = datetime(2019, 1, 1, 12, 0, 1, microsecond=500000 )
diff = end - start

print('Total duration=',diff)
print('Total seconds=', diff.total_seconds())
print('microseconds=', diff.microseconds)
Run Code Online (Sandbox Code Playgroud)
from datetime import datetime, timedelta

start = datetime(2019, 1, 1, 12, 0, 0, 0 )
end   = datetime(2019, 1, 1, 12, 0, 1, microsecond=500000 )
diff = end - start

print('Total duration=',diff)
print('Total seconds=', diff.total_seconds())
print('microseconds=', diff.microseconds)
Run Code Online (Sandbox Code Playgroud)

使用total_seconds1e6并乘以1e6,或者只是更改测试以在几秒钟内报告结果。

注意 C ++应该很容易赢得胜利。循环具有在编译时已知的固定数量的迭代,并且所有计算都不相互依赖。一个好的优化C ++编译器应该对循环进行分块或部分展开,并使用SSE指令并行执行少量计算。