3

私は奇妙な問題に遭遇しました。私はいくつかの線形代数を実装していますが、これまでのところ行列乗算のみを 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 は同じパフォーマンスを維持します。これがなぜなのか説明できる人はいますか?

4

3 に答える 3

1

特に両方のテスト システムのハードウェアが異なる場合は、各コード パスの初期化ルーチン間に数ミリ秒の差が生じる可能性があります。ラップトップと nVidia カードの両方で少なくとも数秒かかる大規模なセットをテストすることから始めることをお勧めします。

于 2011-05-25T14:16:30.097 に答える