Я работаю над внедрением алгоритма FFT с использованием OpenCL (в частности, алгоритм от OpenCL в действии. Он отлично работает на двух разных графических процессорах NVIDIA (Tesla K20c и GeForce GTX 650), но дает мне ошибку сегментации, когда я запускаю ее на своем процессоре Intel.OpenCL segfault при использовании CPU
Я обнаружил проблему в коде ядра, но это не имеет смысла. Единственными двумя строками, которые дают ошибку при их включении, является последние две записи записываются в локальную память в блоке ниже. Никакая другая запись в память не вызывает проблемы для ЦП, и они не создают проблемы на графическом процессоре.
__kernel void fft_init(__global float2 *g_data, __local float2 *l_data,
uint points_per_group, uint size, int dir) {
uint4 br, index;
uint points_per_item, g_addr, l_addr, i, fft_index, stage, N2;
float2 x1, x2, x3, x4, sum12, diff12, sum34, diff34;
points_per_item = points_per_group/get_local_size(0);
l_addr = get_local_id(0) * points_per_item;
g_addr = get_group_id(0) * points_per_group + l_addr;
for(i=0; i<points_per_item; i+=4) {
...
l_data[l_addr] = sum12 + sum34;
l_data[l_addr+1] = diff12 + diff34;
l_data[l_addr+2] = sum12 - sum34;
l_data[l_addr+3] = diff12 - diff34;
l_addr+= 4;
}
Я также знаю, что проблема заключается не в l_addr + {2,3}
, так как далее в ядре к массиву обращается не менее l_addr + 4
.
Неужели кто-нибудь сталкивался с проблемой, подобной этой ранее, или имел какие-либо идеи о том, как я могу ее исправить? Для запуска ядра я использую EnqueueNDRangeKernel, и при настройке аргумента для массива локальной памяти я использую весь доступный размер локальной памяти.
Заранее благодарен!
Я предполагаю, что вы обращаетесь в прошлом к концу массив, который был выделен. Каков размер, который вы ожидаете от массива l_data? (в байтах) и какое значение вы передаете в аргументе size clSetKernelArg? Также, что возвращает clGetDeviceInfo для CL_DEVICE_LOCAL_MEM_SIZE? Соответствует ли оно? Наконец, если ваш использование локальной памяти имеет фиксированный размер (а не динамический), лучшая форма: '__local float localBuffer [1024];' r чем использование аргумента ядра. – Dithermaster
Массив l_data - это точный размер LOCAL_MEM_SIZE, возвращаемый GetDeviceInfo. В этом случае это 32768, и это число, которое я передаю clSetKernelArg. Аргумент указателя для clSetKernelArg равен NULL, и я собираюсь сыграть с этим прямо сейчас, чтобы узнать, не является ли это проблемой. Локальная память динамическая, не фиксированная, поскольку я использую всю локальную память, доступную для устройства, но я буду искать способ сделать это изнутри ядра. – Chris
Игнорируйте то, что я сказал об аргументе NULL выше, я узнал, что так оно и должно быть. Я обнаружил, что в самом маленьком случае l_addr никогда не превышает 'get_local_id (0)'. Поскольку количество рабочих элементов на группу намного меньше, чем LOCAL_MEM_SIZE, я не могу понять, к чему обращается доступ к 'l_data [l_addr + 3]' за концом массива. – Chris