Ядро OpenCL — локальная память работает неправильно

У меня есть тестовое ядро, которое я вызываю из Julia OpenCL API. Тот факт, что я звоню от Джулии, не важен, это просто то, что я использую для запуска OpenCL, вот код:

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 рабочих элемента).

Один местный поплавок x создается для каждой рабочей группы, и первый рабочий элемент в каждой рабочей группе устанавливает его в 0. Затем каждый рабочий элемент в рабочей группе добавляет 1 к нему, и, поскольку в каждой рабочей группе есть два рабочих элемента должно быть 2, но когда я вернусь CВместо этого я получаю вектор единиц.

1

Решение

barrier(CLK_LOCAL_MEM_FENCE);

x += 1.0f;

barrier(CLK_LOCAL_MEM_FENCE);

Барьеры не мьютексы. У вас есть гонка данных, в которой оба рабочих элемента пытаются записать в одну и ту же переменную одновременно.

Вам придется использовать атомарность или изменить код.

3

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]