0

ここで問題が発生しています。2つのカーネルを起動し、期待される値(ホストへのmemcpy)であるかどうかを確認します。停止している場合は停止し、そうでない場合は2つのカーネルを再度起動します。

最初のカーネル:

__global__  void aco_step(const KPDeviceData* data)
{
int obj = threadIdx.x;
int ant = blockIdx.x;
int id = threadIdx.x + blockIdx.x * blockDim.x;

*(data->added) = 1;

while(*(data->added) == 1)
{
    *(data->added) = 0;

    //check if obj fits
    int fits = (data->obj_weights[obj] + data->weight[ant] <= data->max_weight);
    fits = fits * !(getElement(data->selections, data->selections_pitch, ant, obj));

    if(obj == 0)
        printf("ant %d going..\n", ant);
    __syncthreads();

...

この後、コードは続きます。しかし、そのprintfが印刷されることはなく、syncthreadsはデバッグ目的のためだけに存在します。

「追加された」変数は共有されましたが、共有メモリはPITAであり、通常はコードにバグが含まれているため、今のところ削除しました。この「追加された」変数は最も賢い方法ではありませんが、配列内の変数がホスト上の値であるかどうかをチェックし、反復を続けるかどうかを決定する代替手段よりも高速です。

getElementは、ピッチを使用してマトリックスメモリの計算を実行し、正しい位置にアクセスして、そこに要素を返します。

int* el = (int*) ((char*)mat + row * pitch) + col;
return *el;

obj_weights配列には、適切なサイズn * sizeof(int)があります。重み配列、ants * sizeof(float)も同様です。したがって、それらは範囲外ではありません。

この後のカーネルは最初にprintfを持っていて、それも印刷されず、printfの後にデバイスメモリに変数を設定し、カーネルが終了した後にこのメモリがCPUにコピーされます。 CPUコードで出力するときの正しい値ではありません。したがって、このカーネルは違法なことをしていて、2番目のカーネルは起動されていないと思います。

いくつかのインスタンスをテストしていますが、8ブロックと512スレッドを起動すると、正常に実行されます。32ブロック、512スレッド、OK。しかし、8ブロックと1024スレッド、そしてこれが起こると、カーネルは機能せず、32ブロックと1024スレッドも機能しません。

私は何か間違ったことをしていますか?メモリアクセス?起動するスレッドが多すぎませんか?

編集:「追加された」変数とwhileループを削除しようとしたため、1回だけ実行する必要があります。printfが最初の3行の直後にあり、次のカーネルも何も出力しない場合でも、それでも機能せず、何も出力されません。

編集:別のことですが、私はGTX 570を使用しているので、http://en.wikipedia.org/wiki/CUDAによると「ブロックあたりの最大スレッド数」は1024です。たぶん、最大512を維持するか、この値をどれだけ高くできるかを確認します。

4

1 に答える 1

2

__syncthreads()内部条件コードは、条件がブロックのすべてのスレッドで同じように評価される場合にのみ許可されます。

あなたの場合、条件は競合状態に陥り、非決定論的であるため、おそらく異なるスレッドに対して異なる結果に評価されます。

printf()出力は、カーネルが正常に終了した後にのみ表示されます。この場合、上記の問題が原因ではないため、出力は表示されません。これは、すべての CUDA 関数呼び出しのエラーのリターン コードをテストすることで解決できたはずです。

于 2012-09-12T22:50:27.250 に答える