2

GPUを使用して、単語を処理するための計算を行っています。最初は、1 ブロック (500 スレッド) を使用して 1 単語を処理していました。100 ワードを処理するには、メイン関数でカーネル関数を 100 回ループする必要があります。

for (int i=0; i<100; i++)
    kernel <<< 1, 500 >>> (length_of_word); 

私のカーネル関数は次のようになります。

__global__ void kernel (int *dev_length)
{
   int length = *dev_length;
   while (length > 4)
   {   //do something;
          length -=4;
   }
}

ここで、100 語すべてを同時に処理したいと考えています。

各ブロックには引き続き 500 のスレッドがあり、(ブロックごとに) 1 つの単語を処理します。

dev_totalwordarray: 単語のすべての文字を (1 つずつ) 格納します

dev_length_array: 各単語の長さを格納します。

dev_accu_length: 単語の累積的な長さ (前のすべての単語の合計文字数) を格納します

dev_salt_ はサイズ 500 の配列で、符号なし整数を格納します。

したがって、私の主な機能では

   kernel2 <<< 100, 500 >>> (dev_totalwordarray, dev_length_array, dev_accu_length, dev_salt_);

cpu 配列を設定するには:

    for (int i=0; i<wordnumber; i++)
    {
        int length=0;
        while (word_list_ptr_array[i][length]!=0)
        {
            length++;
        }

        actualwordlength2[i] = length;
    }

cpu -> gpu からコピーするには:

    int* dev_array_of_word_length;
    HANDLE_ERROR( cudaMalloc( (void**)&dev_array_of_word_length, 100 * sizeof(int) ) );
    HANDLE_ERROR( cudaMemcpy( dev_array_of_word_length, actualwordlength2, 100 * sizeof(int),

私の関数カーネルは次のようになります。

__global__ void kernel2 (char* dev_totalwordarray, int *dev_length_array, int* dev_accu_length, unsigned int* dev_salt_)
{

  tid = threadIdx.x + blockIdx.x * blockDim.x;
  unsigned int hash[N];

  int length = dev_length_array[blockIdx.x];

   while (tid < 50000)
   {
        const char* itr = &(dev_totalwordarray[dev_accu_length[blockIdx.x]]);
        hash[tid] = dev_salt_[threadIdx.x];
        unsigned int loop = 0;

        while (length > 4)
        {   const unsigned int& i1 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
            const unsigned int& i2 = *(reinterpret_cast<const unsigned int*>(itr)); itr += sizeof(unsigned int);
            hash[tid] ^= (hash[tid] <<  7) ^  i1 * (hash[tid] >> 3) ^ (~((hash[tid] << 11) + (i2 ^ (hash[tid] >> 5))));
            length -=4;
        }
        tid += blockDim.x * gridDim.x;
   }
}

ただし、kernel2 はまったく機能していないようです。

これが while (length > 4) 原因のようです。

誰かが理由を知っていますか?ありがとう。

4

1 に答える 1

1

が原因かどうかはwhileわかりませんが、コードに気になる点がいくつか見られます。

  • カーネルは出力を生成しません。オプティマイザはこれを検出し、空のカーネルに変換します。
  • ほとんどの場合、スレッドごとに配列を割り当てる必要はありません。それは多くのメモリを消費します。テーブルhash[N]はスレッドごとに割り当てられ、カーネルの最後で破棄されます。が大きい場合N(さらにスレッドの合計量を掛けた場合)、GPU メモリが不足する可能性があります。言うまでもなく、へのアクセスは、hashグローバル メモリへのアクセスとほぼ同じくらい遅くなります。
  • ブロック内のすべてのスレッドは同じitr値になります。それは意図されていますか?
  • すべてのスレッドは、テーブルの独自のコピー内の 1 つのフィールドのみを初期化しhashます。
  • グローバルインデックスhash[tid]がどこにあるかがわかります。グローバル化されたとしても、並行性の問題が発生する可能性があることにtid注意してください。hashグリッド内のすべてのブロックが同時に実行されるわけではありません。1 つのブロックが の一部を初期化しますがhash、別のブロックは開始さえしない可能性があります。
于 2012-11-08T08:06:49.787 に答える