0

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];
    }
}
4

1 に答える 1

1

ここで私の考えは、必要なスレッド/ブロックのみを使用して行列の正方形部分を転置し (各スレッドは正方行列の 2 つのエントリを交換します)、残りのエントリをトラバースして転置することでした。

__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; 
      } 
   }

}

カーネルコールは

   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); 

512x256 と 256x512 のマトリックスでテストしました。感想を教えてください。

于 2013-04-09T03:50:14.843 に答える