3

3D マトリックスのデータはレイヤーによって (上から下に) 生成され、そのデータに 2D マトリックスBを乗算したいのですが、各レイヤーを取得する代わりに、レイヤー 1 からベクトル、レイヤー 2 からベクトルを取得する必要があります。すぐ。

現在、私が行っているのは、これらのベクトルを 3D マトリックスから 2D マトリックスtmpAにコピーし、(CUBLAS を使用して) Bで乗算し、結果をtmpBに格納して、最終的に行ごとに 3D マトリックスCに対応する場所にコピーすることです。

全体として、私のアプリ全体は CPU バージョンよりも少なくとも 2 倍高速に実行されますが、デバイスからデバイスへのメモリ コピー (であっても) は、パフォーマンスに関してはまったく良くないように思えます。

この計算を行うより良い方法は何でしょうか? メモリのコピーを避けるために、乗算する前にデータを再配置することを考えていました。

3D マトリックスACおよび 2D マトリックスBは、既に GPU のメモリに格納されています。

編集

M、N、Pを、デバイスのメモリ上の線形配列に行優先順に格納された 3D 行列Aの次元とします。私のコードは次のようになります。

cudaMalloc((void**)&d_tmpIn, sizeof(float)*M*P);
cudaMalloc((void**)&d_tmpOut, sizeof(float)*M*P);
cudaMalloc((void**)&d_C, sizeof(float)*M*N*P);

for (int iN = 0; iN < N; iN++)
{
  dst = d_tmpIn;
  for (int iM = 0; iM < M; iM++)
  {
    cudaMemcpy(dst, &(d_A[iN*P+0+iM*N*P]), sizeof(float)*P, cudaMemcpyD2D);
    dst += P;
  }

  cublasDgemm(cublasHandle, CUBLAS_OP_N, CUBLAS_OP_N, P, M, M, &alpha, d_tmpIn, P, d_B, M, &beta, d_tmpOut, P);

  src = d_tmpOut;
  for (int iM = 0; iM < M; iM++)
  {
    cudaMemcpy(&(d_C[iN*P+0+iM*N*P]), src, sizeof(float)*P, cudaMemcpyD2D);
    src += P;
  }
}

お役に立てれば。

4

1 に答える 1

4

メモリのコピーを行う必要はありません。BLAS および LAPACK API は、開始点、ストライドの長さ、リーディング ディメンションの長さなどを指定できるように作成されました。

このように、3D 配列 A と C をそのまま使用できますが、正しいパラメーターを使用して cublasDgemm を呼び出します。

あなたの場合(コードを正しく理解していれば)、各マトリックスが必要でP X Mあり、それらを持っているように見えNます。しかし、3D配列は次のように配置されているようPxNxMです。d_tmpInしたがって、とにメモリを割り当てなくてd_tmpOutも、次のようなことができます。 の行数AP. 列数はMです。ただし、先頭の寸法 ( lda) は として記載する必要がありますN * P。についても同様ですC

int lda = N * P;
int ldc = N * P;
for (int iN = 0; iN < N; iN++)
{
  double *d_tmpIn = d_A + iN * P;
  double *d_tmpOut = d_C + iN * P;
  cublasSetStream(streams[iN]); // Optional
  cublasDgemm(cublasHandle, CUBLAS_OP_N, CUBLAS_OP_N,
              P, M, M, &alpha, d_tmpIn, lda, d_B, M, &beta, d_tmpOut, ldc);

}

iN ストリームを作成し、各 cublas を個別のストリームで実行することもできます。これは、M と P が十分に小さい場合 (つまり、GPU がまだ計算上飽和していない場合) にのみ有用であることに注意してください。

EDITストリームを使用する予定がある場合は、プログラムの最初に一度ストリームを作成し、再利用してみてください。Dgemm と同じループでストリームを作成および破棄しないでください。これにより、オーバーヘッドが増加します。

于 2013-08-16T19:26:45.723 に答える