c # — Утечка буфера в ядре Opencl после 12k плавающих элементов

Я написал ядро ​​dotproduct для opencl на C ++, и оно работает для длины вектора 4096 (также пробовал 12k элементов и работает без нареканий), но когда я увеличиваю длину вектора до 16k элементов, результат становится бесконечным пока он не должен выходить за пределы небольшого числа с плавающей точкой. Ясно, что есть утечка или что-то подобное, но это нормально работает<16к элементов. 16 КБ элементов и 4 байта каждый составляют 64 КБ, три буфера суммируются до 192 КБ, и это даже не 1/1000 памяти gpu. Сравненный результат с тем же алгоритмом сокращения для кода хоста (C #) и результата хоста мал, как и ожидалось. Также нет погрешностей точности для построения бесконечности (она может даже ограничиваться определенным конечным значением).

Вот ядро ​​(Ln = локальный размер работы, n = глобальный размер работы) из C #, переданное в C ++ через DLL-вызов:

"__kernel void SkalarCarpim(__global float * v1, __global float * v2, __global float * v3)" +
"{" +
"    int i = get_global_id(0);" +
"    int j = get_local_id(0);" +
"    __local float biriktirici [" + Ln.ToString() + "];" +
"    barrier(CLK_LOCAL_MEM_FENCE);" +
"    biriktirici[j]=v1[i]*v2[i];" +
"    barrier(CLK_LOCAL_MEM_FENCE);" +
"    barrier(CLK_GLOBAL_MEM_FENCE);" +
"    float toplam=0.0f;" +
"    if(j==0)" +
"    {" +
"        for(int k=0;k<"+Ln.ToString()+";k++)"+ // reduction
"        {"+
"             toplam+=biriktirici[k];"+
"        }"+
"    }" +
"    barrier(CLK_GLOBAL_MEM_FENCE);" +
"    v3[i]=toplam;" +
"    barrier(CLK_GLOBAL_MEM_FENCE);" +
"    toplam=0.0f;" +
"    for(int k=0;k<"+(n/Ln).ToString()+";k++)" +
"    {" +
"         toplam+=v3[k*"+Ln.ToString()+"];       " + // sum of temporary sums
"    }" +
"    v3[i]=toplam;"+
"}";

Вот буферы C ++ Opencl:

buf1=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
buf2=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
buf3=cl::Buffer(altYapi,CL_MEM_READ_WRITE,sizeof(cl_float) * N);
//CL_MEM_READ_ONLY makes same error, tried some other too, no solution :(

Вот как отправляются буферы:

komutSirasi.enqueueWriteBuffer(buf1,CL_TRUE,0,sizeof(cl_float)*N,v1);
komutSirasi.enqueueWriteBuffer(buf2,CL_TRUE,0,sizeof(cl_float)*N,v2);
//CL_TRUE makes a blocking action so waits until finished

Исполнение:

 komutSirasi.enqueueNDRangeKernel(kernel,0,Global,Local);
//I got this from an example and I dont know if it is blocking or not.

Вот как берется буфер результатов (все элементы являются результатом, я знаю, что он незакончен):

komutSirasi.enqueueReadBuffer(buf3,CL_TRUE,0,sizeof(cl_float) * N,v3);
//CL_TRUE makes a blocking action so waits until finished

Вопрос: Есть ли необходимость в настройке, прежде чем погрузиться в C ++ Opencl? Это не было проблемой в Java / Aparapi / Jocl.

Для этого используйте заголовки Opencl 1.2 с сайта Khronos и AMD Opencl.lib + Opencl.dll (целевое устройство HD7870).

0

Решение

Ваше второе сокращение, сумма v3 [k * N], предполагает, что все значения в v3 уже вычислены. Это потребует синхронизации между различными рабочими группами, что невозможно в общем случае. Это может случайно произойти, когда есть одна рабочая группа.

После первого сокращения вы должны сохранить toplam в v3 [get_group_id (0)], а затем запустить второе ядро ​​для второго сокращения.

3

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

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

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