0

私はこのカーネルを持っています

__global__ void kernel1(int keep, int include, int width, int* d_Xco, 
              int* d_Xnum, bool* d_Xvalid, float* d_Xblas)
{

  int i, k;  
  i = threadIdx.x + blockIdx.x * blockDim.x;

  if(i < keep){

    for(k = 0; k < include ; k++){

      int val = (d_Xblas[i*include + k] >= 1e5);
      int aux = d_Xnum[i];

      d_Xblas[i*include + k] *= (!val);
      d_Xco[i*width + aux] = k;
      d_Xnum[i] +=val;
      d_Xvalid[i*include + k] = (!val);
    }
  }
}

で起動

int keep = 9000;
int include = 23000;
int width = 0.2*include;

int threads = 192;
int blocks = keep+threads-1/threads;
kernel1 <<< blocks,threads  >>>( keep, include, width,
                                 d_Xco, d_Xnum, d_Xvalid, d_Xblas );

これkernel1は正常に機能しますが、完全に最適化されているわけではありません。内側のループをなくすのは簡単だと思いましたkが、どういうわけかうまくいきません。私の最初のアイデアは:

__global__ void kernel2(int keep, int include, int width, 
               int* d_Xco, int* d_Xnum, bool* d_Xvalid, 
               float* d_Xblas)
{

  int i, k;  
  i = threadIdx.x + blockIdx.x * blockDim.x;
  k = threadIdx.y + blockIdx.y * blockDim.y;

  if((i < keep)  && (k < include) ) {

      int val = (d_Xblas[i*include + k] >= 1e5);
      int aux = d_Xnum[i];
      d_Xblas[i*include + k] *= (float)(!val);
      d_Xco[i*width + aux] = k;
      atomicAdd(&d_Xnum[i], val);
      d_Xvalid[i*include + k] = (!val);
  }
}

2Dグリッドで起動:

int keep = 9000;
int include = 23000;
int width = 0.2*include;

int th = 32;
dim3 threads(th,th);
dim3 blocks ((keep+threads.x-1)/threads.x, (include+threads.y-1)/threads.y);
kernel2 <<< blocks,threads >>>( keep, include, width, d_Xco, d_Xnum, 
                               d_Xvalid, d_Xblas );

アイデアは素晴らしいと思いますが、うまくいかず、ここでアイデアが不足しています。ここで私を助けてくれませんか?d_Xcoまた、位置kを小さな配列に格納し、それらを配列の先頭にプッシュするという問題もあると思います。そのため、順序が重要になります。

d_Xco
-------------------------------
| 2|3 |15 |4 |5 |5 | | | | | | .......
-------------------------------
4

1 に答える 1

1

元のコードでは、

for(k = 0; k < include ; k++){
  ...
  int aux = d_Xnum[i];
  ...
  d_Xco[i*width + aux] = k;
  ...
}

配列へのインデックスd_Xcoは依存しないkため、各反復への書き込みは冗長です。最終的な値は常にinclude-1. したがって、ループ内の次の 2 行をループk1 行に置き換えます。k

 d_Xco[i*width + d_Xnum[i]] = include - 1;

これを行うと、ループを並列化すると、多くのスレッドが同時に同じ場所に異なる値を割り当てるkときに現在発生している競合状態がなくなります(順序の保証はありません)。kd_Xco

于 2012-10-10T11:53:01.293 に答える