基準測試(python vs. c++ using BLAS)和(numpy)

| | | | | | | | | | | | | | | | | | | | | | | | | | |

我想編寫一個廣泛使用 BLAS 和 LAPACK 線性代數功能的程序。由於性能是一個問題,我做了一些基準測試,想知道我採用的方法是否合法。

可以這麼說,我有三個參賽者,想用一個簡單的矩陣矩陣來測試他們的表現乘法。參賽者是:

  1. Numpy,僅使用dot的功能。
  2. Python,通過共享對象調用BLAS功能。
  3. C++,通過共享對象調用BLAS功能。

場景

我實現了不同維度的矩陣-矩陣乘法我。 i 從 5 運行到 500,增量為 5,矩陣 m1m2 設置如下:

m1 = numpy.random.rand(i,i).astype(numpy.float32) m2 = numpy.random.rand(i,i).astype(numpy.float32) 

1。 Numpy

使用的代碼如下所示:

tNumpy = timeit.Timer("numpy.dot(m1, m2)", "import numpy; from __main__ import m1 , m2") rNumpy.append((i, tNumpy.repeat(20, 1))) 

2. Python,通過共享對象調用BLAS

使用函數

_blaslib = ctypes.cdll.LoadLibrary("libblas.so") def Mul(m1, m2, i , r): no_trans = c_char("n") n = c_int(i) 一 = c_float(1.0) 零 = c_float(0.0) _blaslib.sgemm_(byref(no_trans), byref(no_trans), byref(n), byref (n), byref(n), byref(one), m1.ctypes.data_as(ctypes.c_void_p), byref(n), m2.ctypes.data_as(ctypes.c_void_p), byref(n), byref(零) , r.ctypes.data_as(ctypes.c_void_p), byref(n)) 

測試代碼如下:

r = numpy.zeros ((i,i), numpy.float32) tBlas = timeit.Timer("Mul(m1, m2, i, r)", "import numpy; from __main__ import i, m1, m2, r, Mul") rBlas。追加((我,tBlas.repeat(20, 1)))

3。 c++,通過共享對象調用 BLAS

現在 c++ 代碼自然要長一些,所以我將信息減少到最少。
我用

void* 句柄 = dlopen("libblas.so", RTLD_LAZY); void* Func = dlsym(handle, "sgemm_"); 

我用 gettimeofday 像這樣測量時間:

gettimeofday(&start, NULL); f(&no_trans, &no_trans, &dim, &dim, &dim, &one, A, &dim, B, &dim, &zero, Return, &dim); gettimeofday(&end, NULL); dTimes[j] = 計算時間(開始,結束); 

其中 j 是一個循環運行 20 次。我用

double CalcTime(timeval start, timeval end) { double factor = 1000000;返回(((雙)end.tv_sec)*因子+((雙)end.tv_usec)-(((雙)start.tv_sec)*因子+((雙)start.tv_usec)))/因子; } 

結果

結果如下圖所示:

enter image description here

問題

  1. 你認為我的做法是否公平,或者我可以做一些不必要的開銷避免?
  2. 您是否期望結果會顯示 c++ 和 python 方法之間存在如此巨大的差異?兩者都使用共享對象進行計算。
  3. 由於我更願意在我的程序中使用 python,所以在調用 BLAS 或 LAPACK 例程時我可以做些什麼來提高性能?

下載

完整的基準測試可以在這裡下載。 (JF Sebastian 使該鏈接成為可能^^)