2016-07-15 8 views
1

Julia OpenCL APIから呼び出しているテストカーネルがあります。私はジュリアからそれを呼んでいるという事実は重要ではありませんが、それは私がOpenCLのを実行するために使用しているだけで何だ、ここのコードです:OpenCLカーネルの_localメモリが正しく動作しない

using OpenCL 
const cl = OpenCL 

device, ctx, queue = cl.create_compute_context() 

C_buff = cl.Buffer(Float32, ctx, :w, 2) 

const testkernel = """ 
kernel void test(global float *C) 
{ 
    int gid = get_global_id(0); 
    int lid = get_local_id(0); 

    local float x; 

    if (lid == 0) 
    { 
     x = 0.0f; 
    } 
    barrier(CLK_LOCAL_MEM_FENCE); 

    x += 1.0f; 

    barrier(CLK_LOCAL_MEM_FENCE); 

    if (lid == 0) 
    { 
     C[gid/2] = x; 
    } 
} 
""" 

program = cl.Program(ctx, source=testkernel) |> cl.build! 
kernel = cl.Kernel(program, "test") 
cl.call(queue, kernel, 4, 2, C_buff) 
cl.read(queue, C_buff) 

私が把握することはできません何がこれはベクトルを返します[1.0,1.0]、それはベクトル[2.0,2.0]を返すはずです。基本的に私は4つの作業項目を2つの作業グループ(それぞれ2つの作業項目を含む)に分割しています。

ローカルフロートは、各作業グループごとにインスタンス化され、各作業グループの最初の作業項目は0に設定されます。次に、作業グループの各作業項目に1が追加されます。各作業グループの作業項目は2でなければなりませんが、Cを返すと、代わりに1のベクトルが得られます。

答えて

3
barrier(CLK_LOCAL_MEM_FENCE); 

x += 1.0f; 

barrier(CLK_LOCAL_MEM_FENCE); 

障壁は、ミューテックスではありません。両方の作業項目が同じ変数に同時に書き込もうとするデータ競合があります。

アトミックを使用するか、コードを再設計する必要があります。

+0

私は彼らが*正確に*同じ時間に書くことはないと思うと思うので、大丈夫です。明示的な再設計は、ローカル変数 'local float x [2]'をインスタンス化し、ワークグループ内の各作業項目に一方または他方の座標を書き込ませ、バリアを呼び出して 'x'を合計することですその後。しかし、それは私のコードの最適ではないリファクタリングのように思えますが、より良いアプローチがありますか? – Thoth

+0

@彼らはまったく同じ時刻に書き込みます。なぜなら、それはSIMDマシンの仕組みであり、たとえそれが起こっていなくてもそうであるからです。(https://en.wikipedia.org/wiki/Race_condition#Example) – Jovasa

+0

ああ!良いリンク、よくそれを説明します。 – Thoth

関連する問題