Matrix 非方矩阵CUDA的通用快速转置

Matrix 非方矩阵CUDA的通用快速转置,matrix,cuda,transpose,Matrix,Cuda,Transpose,SDK提供了一个处理方矩阵转置的示例和策略,但是有没有一种在非方矩阵上执行转置的好方法?我目前有一个非常幼稚的实现,如下所示,这可能很糟糕: template<class S> __global__ void transpose(S *Source, S *Destination, int SizeX, int SizeY) { int tid = threadIdx.x + blockIdx.x * blockDim.x; if (tid<SizeX*Siz

SDK提供了一个处理方矩阵转置的示例和策略,但是有没有一种在非方矩阵上执行转置的好方法?我目前有一个非常幼稚的实现,如下所示,这可能很糟糕:

template<class S>
__global__ void transpose(S *Source, S *Destination, int SizeX, int SizeY) {
    int tid = threadIdx.x + blockIdx.x * blockDim.x;

    if (tid<SizeX*SizeY) {
        int X = tid % SizeX;
        int Y = tid / SizeX;

        //(x,y) => (y,x)

        int newId = (SizeY*X) + Y;
        Destination[newId] = Source[tid];
    }
}
模板
__全局无效转置(S*源、S*目的地、int SizeX、int SizeY){
int tid=threadIdx.x+blockIdx.x*blockDim.x;
若有(tid)(y,x)
int newId=(SizeY*X)+Y;
目的地[newId]=来源[tid];
}
}

在这里,我的想法是只使用必要的线程/块转置矩阵的方形部分(每个线程交换方形子矩阵的两个条目),然后遍历并转置其余条目

__global__ void kernelTranspuesta(float *a, float *c, int m, int n) {
   int i = threadIdx.x + blockIdx.x*blockDim.x; 
   int j = threadIdx.y + blockIdx.y*blockDim.y; 
   int smallest = M < N ? M : N;

   while( j < smallest ){
      i = threadIdx.x + blockIdx.x*blockDim.x;
      while( i < j ){
         c[i*m+j] = a[j*n+i];
         c[j*m+i] = a[i*n+j];
         i+= blockDim.x*gridDim.x; 
      }
      if(i == j)
         c[j*m+i] = a[i*n+j];

     j+= blockDim.y*gridDim.y; 
   }  

   if( M > N ) {
      i = threadIdx.x + blockIdx.x*blockDim.x + N;
      j = threadIdx.y + blockIdx.y*blockDim.y; 

      while( i < M ){
         j = threadIdx.y + blockIdx.y*blockDim.y; 
         while( j < N){
           c[j*m+i] = a[i*n+j];
           j+= blockDim.y*gridDim.y; 
         }
         i+= blockDim.x*gridDim.x; 
      } 
   }else{
      i = threadIdx.x + blockIdx.x*blockDim.x;
      j = threadIdx.y + blockIdx.y*blockDim.y + M; 

     while( i < M ){
         j = threadIdx.y + blockIdx.y*blockDim.y + M; 
         while( j < N){
           c[j*m+i] = a[i*n+j];
           j+= blockDim.y*gridDim.y; 
         }
         i+= blockDim.x*gridDim.x; 
      } 
   }

}
\uuuu全局\uuuuu无效内核传输(浮点*a,浮点*c,整数m,整数n){
int i=threadIdx.x+blockIdx.x*blockDim.x;
int j=线程IDX.y+块IDX.y*块DIM.y;
int最小值=MN){
i=线程IDX.x+块IDX.x*blockDim.x+N;
j=螺纹内径x.y+块内径x.y*blockDim.y;
而(我
内核调用是

   dim3 hilos(16,16);   // hilos(blockDim.x, blockDim.y) 
   dim3 bloques(8,8); // bloques(gridDim.x, gridDim.y)

   kernelTranspuesta<<<bloques, hilos>>>(aD, cD, m, n); 
dim3hilos(16,16);//hilos(blockDim.x,blockDim.y)
dim3 bloques(8,8);//bloques(gridDim.x,gridDim.y)
核运输(aD,cD,m,n);

我在512x256和256x512矩阵上进行了测试,请告诉我您的想法。

为什么“可能很糟糕”-你对内核进行了基准测试吗?它达到了峰值内存带宽的多少?可能很糟糕,因为我以前没有测试过它。探查器报告了27GB/s的写入吞吐量和5.3GB/s的读取。可能最好是将块读入共享内存,进行转置并写入块。你在这里的写入根本没有合并。没有如果你有非正方形的任意大小的行/列,这似乎不是确定块大小的可靠方法?看起来不错,我通常在3000x2000左右的矩阵上。在共享内存空间中进行转置不是更快吗?