1. ホーム
  2. c++

[解決済み] ベンチマーク(BLASによるpythonとc++)と(numpy)

2022-10-01 20:43:42

質問

BLASとLAPACKの線形代数機能を多用するプログラムを書きたいと思っています。パフォーマンスが問題なので、私はいくつかのベンチマークを行い、私が取ったアプローチが正当であるかどうかを知りたいと思います。

私は、いわば 3 人の競争相手を持っており、単純な行列-行列の乗算で彼らのパフォーマンスをテストしたいと思います。参加者は次のとおりです。

  1. の機能だけを利用したNumpy。 dot .
  2. Python、共有オブジェクトを通してBLASの機能性を呼び出します。
  3. C++、共有オブジェクトを通してBLASの機能性を呼び出します。

シナリオ

異次元の行列-行列の掛け算を実装してみた i . 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)
    one = c_float(1.0)
    zero = 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(zero), 
            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.append((i, tBlas.repeat(20, 1)))

3. c++で、共有オブジェクトを通してBLASを呼び出す。

さて、c++のコードは当然ながら少し長くなるので、情報を最小限にしています。

で関数を読み込んでいます。

void* handle = 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] = CalcTime(start, end);

ここで j は20回実行されるループです。で経過時間を計算しています。

double CalcTime(timeval start, timeval end)
{
double factor = 1000000;
return (((double)end.tv_sec) * factor + ((double)end.tv_usec) - (((double)start.tv_sec) * factor + ((double)start.tv_usec))) / factor;
}

結果

結果は以下のプロットで示されます。

質問

  1. 私のアプローチは公平だと思いますか、それとも私が避けることのできる不必要なオーバーヘッドがありますか?
  2. c++ と python のアプローチで、結果がこれほど大きな食い違いを示すと予想されますか? 両方とも、計算に共有オブジェクトを使用しています。
  3. 私のプログラムには python を使用したいので、BLAS または LAPACK ルーチンを呼び出す際のパフォーマンスを向上させるにはどうしたらよいでしょうか?

ダウンロード

完全なベンチマークをダウンロードすることができます はこちら . (J.F.セバスチャンのおかげでこのリンクが実現しました^^)

どのように解決するのですか?

私は ベンチマーク . 私のマシンでは、C++とnumpyの間に違いはありません。

私のアプローチは公平だと思いますか?それとも、私が避けることのできる不必要なオーバーヘッドがありますか?

結果に差がないため、公正であると思われます。

<ブロッククオート

c++とpythonのアプローチで、結果がこれほど大きな不一致を示すと予想されますか?両方とも、計算に共有オブジェクトを使用しています。

いいえ。

<ブロッククオート

私のプログラムには python を使いたいので、BLAS または LAPACK ルーチンを呼び出す際のパフォーマンスを上げるにはどうしたらよいでしょうか。

numpyがシステム上でBLAS/LAPACKライブラリの最適化されたバージョンを使用していることを確認してください。