ここで問題が発生しています。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を維持するか、この値をどれだけ高くできるかを確認します。