我正在使用gcc 9.1.0,Eigen 3.3.7,Python 3.7.3和Numpy 1.16.4。
可能的解释:
C++程序没有使用矢量化 Numpy比我想象的要优化得多 时间在每个程序中测量的内容不同
在Stack Overflow上有一个类似的问题(Eigen Matrix vs Numpy Array multiplication performance)。我在我的计算机上进行了测试,并得到了预期的结果,即eigen比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)
C++代码使用Eigen3 (main_eigen.cpp)
编译命令: 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.210664秒
经过时间:0.215406秒
经过时间:0.222483秒
经过时间:0.21526秒
经过时间:0.216346秒
经过时间:0.218951秒
经过时间:0.21587秒
经过时间:0.213639秒
经过时间:0.219399秒
经过时间:0.213403秒
带有eigen3的普通C++
经过时间:0.21052秒
经过时间:0.220779秒
经过时间:0.216269秒
经过时间:0.229234秒
经过时间:0.212265秒
经过时间:0.256714秒
经过时间:0.212396秒
经过时间:0.248241秒
经过时间:0.241537秒
经过时间:0.323519秒
Python
持续时间:0.23946428298950195秒
持续时间:0.1663036346435547秒
持续时间:0.17225909233093262秒
持续时间:0.15922021865844727秒
持续时间:0.16628384590148926秒
持续时间:0.15654635429382324秒
持续时间:0.15859222412109375秒
持续时间:0.1633443832397461秒
持续时间:0.1685199737548828秒
持续时间:0.16393446922302246秒
numpy
函数调用中会将a*a1
转换为一定程度的Python解释,但大部分操作都是在编译后的('C')numpy
代码中进行的。对于像这样的基本数学运算,numpy
多维数组的实现非常高效。 - hpaulj