2016-06-19 4 views
0

みんな。get_global_size(0)はコントローラをクラッシュさせます

私はこのカーネルを得た:

__kernel void FuncionCL(__global char* in, __global char* out, __global int* S2) 
{ 
    __private int op1, op2, op3; 
    __private int C; 
    __private uint WorkDim, C2; 
    op1 = 1; 
    op2 = 2; 
    WorkDim = get_global_size(0); 
    __private int ID; 
    ID = get_global_id(0); 
    for(C = 0; C < 1000000; C++) 
    { 
     for(C2 = ID; C2 < 1000; C2 += WorkDim) 
     { 
      op3 = op1 + op2; 
     } 
    } 
    out[0] = 90; 
    out[1] = 89; 
    *S2 = (int) WorkDim; 
} 

それはあまりにアプリケーション、グラフィックコントローラだけでなく、クラッシュします。私は定数値 '16'(get_global_size()関数が返す)のインクリメントを変更すると、コードは正常に実行されます。どうしたの?するのではなく、8行目に

WorkDim = 16; 

:私は、コードを実行した場合

WorkDim = get_global_size(0); 

コードは、それが問題だ、400倍高速に実行されます。値が同じ場合はなぜですか?

** EDIT:**、コードは非常に遅く、乗算理由がある理由さて、今私が知っている:

1.-占有率が。

2.-すべてのスレッドは、最初のループで同じ繰り返しを行うには、右のコードは次のようになります。

__kernel無効FuncionCL(__globalのchar *うち、中__グローバルのchar *、int型__global * S2) { __private int op1、op2、op3; __private int C; __private uint WorkDim、C2; op1 = 1; op2 = 2; WorkDim = get_global_size(0); __private int ID; ID = get_global_id(0); ため {(C = ID; C + = WorkDim; C < 1000000)のための(C2 = ID; C2 < 1000; C2 + = WorkDim) {OP3 = OP1 + OP2。 } } out [0] = 90; out [1] = 89; * S2 =(int)WorkDim; }

私のコードは、CPUよりもGPUで6.1倍速いです。

+0

すぐにクラッシュするのですか、(5〜10秒のように)しばらくしてクラッシュしますか?後者の場合、カーネルが時間がかかりすぎるため、GPUをリセットするのはOS GPUのウォッチドッグタイマーです。理想的には、あなたのカーネルが50ミリ秒未満になるようにするか、システムの応答性に影響を与え始めてください(UI描画などにも使用されるため)。 – Dithermaster

+0

あなたの答えをありがとう。はい、5秒後にクラッシュします。しかし、その理由はなぜですか?それは、WorkDimの値の代わりに定数値のincrmentを使用すると、カーネルは '16'(get_global_size(0)の値を返す)を返します。 –

答えて

0

1000000 * 1000 = 1Gopの各項目があります。あまりにも時間がかかりすぎると、ドライバがGPUを再起動します。 (あなたの例ではグローバルサイズは1だと思っています)

ほとんどの作業項目でCLカーネルを動かすのは無駄な資源で、GPUはほぼシリアル計算を行い、時間がかかります。

リソースを最大限に活用するには、新しいGPUに少なくとも1024のグローバルアイテムが必要です。

EDIT:ループはおそらく、静的な値を持つコンパイラによって最適化されます。したがって、「驚くべき」スピードアップを実現します。

+0

私は、1Gflopはあまりにも多くのことを請け負いますが、 "WorkDim = 16;"ループでコードを実行すると、 WorkDim = get_global_size(0)よりも速く実行されます。私は100 * 1000回の反復でコードを実行しています。両方のコード間の時間差は、 "get_global_size(0)"で返される値で約400倍遅くなります。さて、私はGeForce 210(16 CUDAコア)を持っているので、なぜ私は16個の作業項目でこのコードを実行しているのですか? –

+0

そのように設計する必要があります。必要に応じて多くの項目を起動し、できるだけ並列化させる必要があります。ちょうど16の項目を使用してすべてのデバイスを使用しているわけではありません(各CUDAコアは、最新のデバイス、つまり64以上の多くのアイテムを起動できます)。 – DarkZeros

+0

これをハードコーディングしてパフォーマンスを向上させる理由は、コンパイラの最適化を推測するのが容易です。ループの有用なデータを保存しておらず、ループパラメータが可変であれば最適化することはできませんが、静的であればループ全体を単純に削除します。 – DarkZeros

関連する問題