我有一个非常简单的 cuda 内核示例,它添加了两个矩阵的相应行。我对矩阵的内存访问有疑问。我通过 mexfunction 调用内核。我们知道在 matlab 中我们有一个列优先顺序访问,而在 C/C++ 中我们有一个行优先顺序。基于 cuda 内存组织,我们在每个块和线程的网格内都有坐标 (x,y)。我试图用两种方式访问内核示例中的矩阵行/列主要顺序 [ 1]。在第一个内核中,如果我错了,请纠正我,有一个列主要访问,而在第二个内核中是行主要访问。两个内核都使用相同的参数、块数和帧数进行初始化。我相信使用矩阵的行主顺序访问的第二个内核将是访问矩阵的正确方法,就像我们在 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;
}