我试图获取各种尺寸的SDK矩阵转置样本的变体。简而言之,我必须采用一个输入数组(double * a)并将其写在一个更大的矩阵(double * tab)的两个不同部分(你会注意到不同的偏移)上。我以行主格式存储数据,所以我使用这个宏进行索引:
#define IDX2L(i,j,ld) (((i)*ld))+(j)) // 0 based index +row-major format
这是我使用的简单代码。
__global__ void cuda_a_Coalesced(double *tab, int tab_rows, int a_rows, double *a)
{
__shared__ double tile[16*(16+1)];
int col = threadIdx.x + blockIdx.x * blockDim.x;
int row = threadIdx.y + blockIdx.y * blockDim.y;
int col_2, row_2;
int a_cols=tab_rows-a_rows; // tab_rows-a_rows is the number of columns of a
int tab_cols=2*tab_rows+2; // 2*tab_rows+2 is the number of columns of tab
if( (col<a_cols) && (row<a_rows) )
{
// Load the data into shared mem
tile[threadIdx.x+threadIdx.y*(16+1)]=a[IDX2L(row,col,a_cols)];
// Normal copy (+ offsets)
tab[IDX2L(row,col+tab_rows+a_rows,tab_cols)]= tile[threadIdx.x+threadIdx.y*(16+1)];
// New idx
col_2 = blockIdx.y * blockDim.y + threadIdx.x;
row_2 = blockIdx.x * blockDim.x + threadIdx.y;
}
__syncthreads();
if( (row_2<a_cols) && (col_2<a_rows) )
// Transpose (+ other offsets)
tab[IDX2L(row_2+a_rows,col_2+tab_rows,tab_cols)]= -tile[threadIdx.y+threadIdx.x*(16+1)];
}
启动参数如下:
b1=(int)ceil((float)a_cols/16);
b2=(int)ceil((float)a_rows/16);
dim bck(b1,b2):dim th(16,16);
cuda_a_Coalesced<<<bck,th>>>(tab,tab_rows,a_rows,a);
无论大小如何,都可以很好地执行正常复制。转置副本仅适用于块大小的整数倍的大小(如SDK示例中所示)。当转置复制失败时,操作的某些部分是正确的,而其他部分则不是,我无法准确预测或跟踪。注意,这个想法是更改共享内存中的索引,以便可以在输出矩阵中以合并的形式写入转置(由于行主格式)。
有人可以告诉我代码只适用于那种尺寸的原因吗?
有没有办法解决这种情况?
答案 0 :(得分:2)
问题是由于某些未定义的线程,因为col_2和row_2的值是在if()语句中分配的,没有所有线程都在访问。
为了解决这种情况,我们可以在声明这些变量时删除col_2和row_2的值,并删除所提到的if()中的同名计算:
__shared__ double tile[16*(16+1)];
int col = threadIdx.x + blockIdx.x * blockDim.x;
int row = threadIdx.y + blockIdx.y * blockDim.y;
int col_2 = blockIdx.y * blockDim.y + threadIdx.x;
int row_2 = blockIdx.x * blockDim.x + threadIdx.y;
int a_cols=tab_rows-a_rows;
int tab_cols=2*tab_rows+2;
因此,其余代码如下所示:
if( (col<a_cols) && (row<a_rows) )
{
// Load the data into shared mem
tile[threadIdx.x+threadIdx.y*(16+1)]=a[IDX2L(row,col,a_cols)];
// Normal copy (+ offsets)
tab[IDX2L(row,col+tab_rows+a_rows,tab_cols)]= tile[threadIdx.x+threadIdx.y*(16+1)];
}
__syncthreads();
if( (row_2<a_cols) && (col_2<a_rows) )
// Transpose (+ other offsets)
tab[IDX2L(row_2+a_rows,col_2+tab_rows,tab_cols)]= -tile[threadIdx.y+threadIdx.x*(16+1)];