Python numpy代码比eigen3或纯C ++更有效

时间:2019-07-10 16:39:34

标签: python c++ performance numpy eigen3

我在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

0 个答案:

没有答案