1

プロジェクトの 1 つに CUDA の最適化を導入しようとしています。しかし、私はここで何か間違ったことをしていると思います。result単純な行列とベクトルの乗算 ( = matrix* )を実装したいと考えていvectorます。しかし、結果をホストにコピーしようとすると、エラーが発生します ( cudaErrorLaunchFailure)。カーネル ( ) にエラーがありますか、それとも間違ってmatrixVectorMultiplicationKernel呼び出しましたか? cudaMemcpyこの種のエラー状態に関する有用なドキュメントは見つかりませんでした。最初の発生後にこのエラーを再度取得せずに CUDA カーネルを呼び出すことができないため、これにより GPU の状態が完全に破壊されると思います。

edit#1: leftaroundabout のアドバイスに従って、コードを更新しました。

// code
...
Eigen::MatrixXf matrix(M, N); // matrix.data() usually should return a float array
Eigen::VectorXf vector(N);    // same here for vector.data()
Eigen::VectorXf result(M);
... // fill matrix and vector
float* matrixOnDevice = copyMatrixToDevice(matrix.data(), matrix.rows(), matrix.cols());
matrixVectorMultiplication(matrixOnDevice, vector.data(), result.data(), matrix.rows(), cm.cols());
... // clean up

// helper functions
float* copyMatrixToDevice(const float* matrix, int mRows, int mCols)
{
  float* matrixOnDevice;
  const int length = mRows*mCols;
  const int size = length * sizeof(float);
  handleCUDAError(cudaMalloc((void**)&matrixOnDevice, size));
  handleCUDAError(cudaMemcpy(matrixOnDevice, matrix, size, cudaMemcpyHostToDevice));
  return matrixOnDevice;
}

void matrixVectorMultiplication(const float* matrixOnDevice, const float* vector, float* result, int mRows, int mCols)
{
  const int vectorSize = mCols*sizeof(float);
  const int resultSize = mRows*sizeof(float);
  const int matrixLength = mRows*mCols;
  float* deviceVector;
  float* deviceResult;
  handleCUDAError(cudaMalloc((void**)&deviceVector, vectorSize));
  handleCUDAError(cudaMalloc((void**)&deviceResult, resultSize));
  handleCUDAError(cudaMemset(deviceResult, 0, resultSize));
  handleCUDAError(cudaMemcpy(deviceVector, vector, vectorSize, cudaMemcpyHostToDevice));
  int threadsPerBlock = 256;
  int blocksPerGrid = (mRows + threadsPerBlock - 1) / threadsPerBlock;
  matrixVectorMultiplicationKernel<<<blocksPerGrid, threadsPerBlock>>>(matrixOnDevice, vector, result, mRows, mCols, matrixLength);
  // --- no errors yet ---
  handleCUDAError(cudaMemcpy(result, deviceResult, resultSize, cudaMemcpyDeviceToHost)); // cudaErrorLaunchFailure
  handleCUDAError(cudaFree(deviceVector)); // cudaErrorLaunchFailure
  handleCUDAError(cudaFree(deviceResult)); // cudaErrorLaunchFailure
}

__global__ void matrixVectorMultiplicationKernel(const float* matrix, const float* vector, float* result, int mRows, int mCols, int length)
{
  int row = blockDim.x * blockIdx.x + threadIdx.x;
  if(row < mRows)
  {
    for(int col = 0, mIdx = row*mCols; col < mCols; col++, mIdx++)
      result[row] += matrix[mIdx] * vector[col];
  }
}
4

1 に答える 1

3

問題は、void copyMatrixToDevice(..., float* matrixOnDevice, ...)このポインターを値で受け取ることです。つまり、デバイスマトリックスを「出力」できません。void copyMatrixToDevice(..., float** matrixOnDevice, ...)によって呼び出され、でそれを行うことができます

copyMatrixToDevice(matrix.data(), &matrixOnDevice, matrix.rows(), matrix.cols());

にも同じ問題がありresultますmatrixVectorMultiplication

長期的には、C++ では、これらすべてに適切なクラス抽象化レイヤーを配置する必要があります。

于 2012-04-16T16:42:54.327 に答える