我在Python3中有一些代码(带numpy),我想将其转换为C ++(具有eigen3),以便获得更高效的程序。因此,我决定测试一个简单的示例来评估我将获得的性能提升。该代码由两个随机数组组成,这两个数组将按系数相乘。我的结论是,带有numpy的python代码比C ++中的代码快30%。我想知道为什么解释的python代码比编译的C ++代码要快。我在C ++代码中缺少什么吗?
我正在使用gcc 9.1.0,Eigen 3.3.7,Python 3.7.3和Numpy 1.16.4。
可能的解释:
C ++程序未使用矢量化
Numpy比我想象的要优化得多
时间正在衡量每个程序中的不同事物
堆栈溢出(Eigen Matrix vs Numpy Array multiplication performance)中也有类似的问题。我在计算机上对此进行了测试,并得到了预期的结果,即本征比numpy更有效,但是这里的运算是矩阵乘法,而不是系数乘积。
Python代码(main.py)
执行命令:python3 main.py
import numpy as np
import time
Lx = 4096
Ly = 4000
# Filling arrays
a = np.random.rand(Lx, Ly).astype(np.float64)
a1 = np.random.rand(Lx, Ly).astype(np.float64)
# Coefficient-wise product
start = time.time()
b = a*a1
# Compute the elapsed time
end = time.time()
print(b.sum())
print("duration: ", end-start)
带有eigen3(main_eigen.cpp)的C ++代码
编译命令:g ++ -O3 -I / usr / include / eigen3 / main_eigen.cpp -o prog_eigen
#include <iostream>
#include <chrono>
#include "Eigen/Dense"
#define Lx 4096
#define Ly 4000
typedef double T;
int main(){
// Allocating arrays
Eigen::Array<T, -1, -1> KPM_ghosts(Lx, Ly), KPM_ghosts1(Lx, Ly), b(Lx,Ly);
// Filling the arrays
KPM_ghosts.setRandom();
KPM_ghosts1.setRandom();
// Coefficient-wise product
auto start = std::chrono::system_clock::now();
b = KPM_ghosts*KPM_ghosts1;
// Compute the elapsed time
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
// Print the sum so the compiler doesn't optimize the code away
std::cout << b.sum() << "\n";
return 0;
}
纯C ++代码(main.cpp)
编译命令:g ++ -O3 main.cpp -o prog
#include <iostream>
#include <chrono>
#define Lx 4096
#define Ly 4000
#define N Lx*Ly
typedef double T;
int main(){
// Allocating arrays
T lin_vector1[N];
T lin_vector2[N];
T lin_vector3[N];
// Filling the arrays
for(unsigned i = 0; i < N; i++){
lin_vector1[i] = std::rand()*1.0/RAND_MAX;
lin_vector2[i] = std::rand()*1.0/RAND_MAX;
}
// Coefficient-wise product
auto start = std::chrono::system_clock::now();
for(unsigned i = 0; i < N; i++)
lin_vector3[i] = lin_vector1[i]*lin_vector2[i];
// Compute the elapsed time
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
// Print the sum so the compiler doesn't optimize the code away
double sum = 0;
for(unsigned i = 0; i < N; i++)
sum += lin_vector3[i];
std::cout << "sum: " << sum << "\n";
return 0;
}
每个程序的运行时间10次
普通C ++
耗用时间:0.210664s
耗用时间:0.215406s
耗用时间:0.222483s
耗用时间:0.21526s
耗用时间:0.216346s
耗用时间:0.218951s
耗用时间:0.21587s
耗用时间:0.213639s
耗用时间:0.219399s
耗用时间:0.213403s
使用eigen3的普通C ++
耗用时间:0.21052s
耗用时间:0.220779s
耗用时间:0.216269s
耗用时间:0.229234s
耗用时间:0.212265s
耗用时间:0.256714s
耗用时间:0.212396s
耗用时间:0.248241s
耗用时间:0.241537s
耗用时间:0.323519s
Python
持续时间:0.23946428298950195
持续时间:0.1663036346435547
持续时间:0.17225909233093262
持续时间:0.15922021865844727
持续时间:0.16628384590148926
持续时间:0.15654635429382324
持续时间:0.15859222412109375
持续时间:0.1633443832397461
持续时间:0.1685199737548828
持续时间:0.16393446922302246