BLASとLAPACKの線形代数機能を多用するプログラムを書きたいと思います。パフォーマンスが問題であるため、ベンチマークを実行しました。私が採用したアプローチが正当であるかどうかを知りたいと思います。
私には、いわば3人の出場者がいて、単純な行列-行列乗算を使用して彼らのパフォーマンスをテストしたいと思います。出場者は次のとおりです。
- Numpy、の機能のみを利用しています
dot
。 - Python、共有オブジェクトを介してBLAS機能を呼び出します。
- C ++、共有オブジェクトを介してBLAS機能を呼び出します。
シナリオ
さまざまな次元の行列-行列乗算を実装しましたi
。i
5から500まで、5の増分と行列m1
で実行され、次のm2
ように設定されます。
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;
}
結果
結果を以下のプロットに示します。
質問
- 私のアプローチは公平だと思いますか、それとも回避できる不要なオーバーヘッドがありますか?
- 結果は、c ++とpythonのアプローチの間にこのような大きな矛盾を示すと思いますか?どちらも計算に共有オブジェクトを使用しています。
- プログラムにPythonを使用したいので、BLASまたはLAPACKルーチンを呼び出すときにパフォーマンスを向上させるために何ができますか?
ダウンロード
完全なベンチマークはここからダウンロードできます。(JFセバスティアンはそのリンクを可能にしました^^)