Случайное поведение ядра OpenCL при превышении определенного размера системы - PullRequest
1 голос
/ 01 апреля 2012

У меня такая проблема. В принципе, у меня есть 2D-сетка, выделенная на хосте:

double* grid = (double*)malloc(sizeof(double)*(ny*nx) * 9);

Следуя обычной процедуре openCL, чтобы поместить ее на устройство openCL:

cl_mem cl_grid = clCreateBuffer(context, CL_MEM_COPY_HOST_PTR, sizeof(double) * (ny*nx) * 9, grid, &error);

И поставить в очередь и запустить:

clEnqueueNDRangeKernel(queue, foo, 1, NULL, &global_ws, &local_ws, 0, NULL, NULL);

В функции ядра простая арифметика выполняется для 1-го столбца сетки:

__kernel void foo(__constant ocl_param* params, __global double* grid)
{
    const int ii = get_global_id(0);
    int jj;
    jj=0;

    if (ii < params->ny) {
        grid[getIndexUsingMacro(ii,jj)] += params->someNumber;
    }
}

И, наконец, прочитайте буфер и проверьте значения.

clEnqueueReadBuffer(queue, cl_grid, CL_TRUE, 0, sizeof(double) * 9 * nx * ny, checkGrid, 0, NULL, NULL);

Проблема в том, что размер сетки (то есть nx * ny * 9) превышает 16384 * 9 * 8 байт = 1152 КБ (* 8, поскольку используется двойная точность).

  • при использовании openCL на ЦП при запуске ядра выдается ошибка CL_OUT_OF_RESOURCES, независимо от того, что я установил для global_ws и local_ws (я установил их в 1, и ошибка все еще выдается). Процессор Intel i5 2415m с 8 ГБ оперативной памяти и 3 МБ кэш-памяти.

  • При использовании openCL на графическом процессоре (NVIDIA TESLA M2050) ошибки не выдается. Однако при чтении значения из буфера сетка не изменяется вообще. Это означает, что он возвращает сетку, значения которой точно такие же, как перед отправкой в ​​функцию ядра.

Например, Когда я устанавливаю nx = 30, ny = 546, nx * ny = 16380, все работает нормально. Сетка вернулась с результатами, которые изменились, как и ожидалось. Но когда ny = 547, nx * ny = 16410, проблема возникает как на CPU, так и на GPU, как описано выше. Проблема та же, если я поменяю местами nx и ny, следовательно, если nx = 547, ny = 30, это все равно происходит. Ребята, можете подсказать, в чем здесь проблема?

Большое спасибо

1 Ответ

1 голос
/ 02 апреля 2012

Похоже, проблема синхронизации.grid[index] += value с одинаковым значением index может выполняться одновременно несколькими рабочими элементами.Эта операция не является атомарной, и все эти рабочие элементы будут загружать grid[index], добавлять свое значение и сохранять его обратно, возможно, теряя при этом некоторые приращения.

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

Другая возможность состоит в том, чтобы гарантировать, что только один рабочий элемент способен изменять данный элемент сетки (обычно это лучшее решение).

Если нескольким рабочим элементам необходимо работать с общим подмножеством сетки, может быть полезным использование локальной памяти и барьеров локальной памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...