У меня был некоторый код на Python3 (с numpy), который я хотел преобразовать в C ++ (с eigen3), чтобы получить более эффективную программу. Поэтому я решил протестировать простой пример, чтобы оценить прирост производительности, который я получу. Код состоит из двух случайных массивов, которые необходимо умножить на коэффициент. Мои выводы заключались в том, что код на python с numpy примерно на 30% быстрее, чем в C ++. Я хотел бы знать, почему интерпретируемый код Python быстрее, чем скомпилированный код C ++. Я что-то упустил в коде C ++?
Я использую gcc 9.1.0, Eigen 3.3.7, Python 3.7.3 и Numpy 1.16.4.
Возможные объяснения:
Программа на C ++ не использует векторизацию
Numpy намного более оптимизирован, чем я думал
Время измеряет разные вещи в каждой программе
Существует аналогичный вопрос в Переполнении стека ( Сравнение Eigen Matrix и Numpy Array ). Я проверил это на своем компьютере и получил ожидаемый результат, что 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 с
Обычный C ++ с собственным 3
прошедшее время: 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