私は奇妙な問題に遭遇しました。私はいくつかの線形代数を実装していますが、これまでのところ行列乗算のみを OpenCL で実装しており、ラップトップでこれをテストしています。コードは非常に単純です。
__kernel void matrix_mult(__global float* a,
__global float* b,
__global float* c,
const int N)
{
int row = get_global_id(1);
int col = get_global_id(0);
float sum = 0.0f;
for (int i = 0; i < N; i++) {
sum += a[row*N+i] * b[i*N+col];
}
c[row*N+col] = sum;
}
次のようにコードを 100 回実行して、ハードウェアをテストします。
clock_t begin=clock();
const unsigned int repeats = 100;
for(int i = 0; i != repeats; i++){
runCL(a, b, results,N, N*N);
}
clock_t end=clock();
私の MBP では、matrix_multiplications はサイズ 512*512 の行列で約 1.2 ミリ秒かかり、GTX 480 Linux ボックスで同じコードを実行すると約 3 ミリ秒かかります。高価な GTX カードがラップトップより少し速いとは思わないので、これは気になります。
私が見ることができる限り、私のコードは「間違っている」か、間違った方法でタイミングを取っています。
OpenCL 仕様でイベントベースのタイミング システムを使用してみました。これにより、もう少し現実的な結果が得られました。
cl_event event = {0};
err = clEnqueueNDRangeKernel(cmd_queue, kernel[0], 2, NULL, global_work_size, NULL, 0, NULL, &event);
assert(err == CL_SUCCESS);
cl_int err = clWaitForEvents (1,&event);
cl_ulong start, end;
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_END, sizeof(cl_ulong), &end, NULL);
clGetEventProfilingInfo(event, CL_PROFILING_COMMAND_START, sizeof(cl_ulong), &start, NULL);
double executionTimeInMilliseconds = (end - start) * 1.0e-6f;
std::cout << "execution time in milis : " << executionTimeInMilliseconds << std::endl;
これで、GT330M は 46 ミリ秒で操作を実行し、GTX480 は 2.5 ミリ秒で操作を実行します。これは、別の非常に興味深い質問になります。PROFILING をオンにすると、GT 330M は約 30 倍遅くなります。これは理にかなっていますが、GTX480 は同じパフォーマンスを維持します。これがなぜなのか説明できる人はいますか?