2 つの行列の対応する行を追加する cuda カーネルの非常に単純な例があります。行列のメモリ アクセスについて質問があります。mexfunction を介してカーネルを呼び出します。matlab では列優先の順序でアクセスし、C/C++ では行優先の順序でアクセスすることがわかっています。cuda メモリ構成に基づいて、各ブロックとスレッドのグリッド内に座標 (x,y) があります。行/列優先の順序 [ 1]。最初のカーネルでは、間違っていたら訂正してください。2 番目のカーネルでは行優先のアクセスであるのに対し、列優先のアクセスがあります。両方のカーネルは、同じパラメーター、ブロック数、およびフレーム数で初期化されます。私は、行列の行優先順アクセスを使用する 2 番目のカーネルが、C++ の場合と同様に、行列にアクセスする正しい方法であると信じていました。残念ながら、列優先のカーネルは、アルゴリズムに従って正しい結果を返します。誰か良い説明がありますか?この観察結果は、mexfunction を介してカーネルを呼び出すという事実と関係がありますか?これは、matlab を意味し、結果として列優先のアクセスを意味しますか?
両方のカーネルは次のように呼ばれます。
int numElements = rows * cols; // rows and cols of d_A or d_B
int threadsPerBlock = 16;
int blocksPerGrid = ceil( (double) (numElements) / threadsPerBlock);
dim3 dimBlock( threadsPerBlock,threadsPerBlock );
dim3 dimGrid( blocksPerGrid, blocksPerGrid );
cudaEuclid<<<dimGrid, dimBlock>>>( d_A, d_B, d_C, rows, cols );
カーネル 1: (動作していますが、行優先の C++ スタイルではありません)
__global__ void cudaEuclid( float* A, float* B, float* C, int rows, int cols )
{
int i, squareeucldist = 0;
int r = blockDim.x * blockIdx.x + threadIdx.x; // rows
int c = blockDim.y * blockIdx.y + threadIdx.y; // cols
if( r < rows ){
for ( i = 0; i < cols; i++ )
//column-major order
squareeucldist += ( A[r + rows*i] - B[r + rows*i] ) * ( A[r + rows*i] - B[r + rows*i] );
C[r] = squareeucldist;
squareeucldist = 0;
}
}
カーネル 2: (行優先順、C++ スタイル)
__global__ void cudaEuclid( float* A, float* B, float* C, int rows, int cols )
{
int i, squareeucldist = 0;
int c = blockDim.x * blockIdx.x + threadIdx.x; // cols
int r = blockDim.y * blockIdx.y + threadIdx.y; // rows
if( r < rows ){
for ( i = 0; i < cols; i++ )
//row-major order
squareeucldist += ( A[i + cols*r] - B[i + cols*r] ) * ( A[i + cols*r] - B[i + cols*r] );
C[r] = squareeucldist;
squareeucldist = 0;
}