2014-01-17 4 views
1

Я работаю над внедрением алгоритма 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, и при настройке аргумента для массива локальной памяти я использую весь доступный размер локальной памяти.

Заранее благодарен!

+0

Я предполагаю, что вы обращаетесь в прошлом к ​​концу массив, который был выделен. Каков размер, который вы ожидаете от массива l_data? (в байтах) и какое значение вы передаете в аргументе size clSetKernelArg? Также, что возвращает clGetDeviceInfo для CL_DEVICE_LOCAL_MEM_SIZE? Соответствует ли оно? Наконец, если ваш использование локальной памяти имеет фиксированный размер (а не динамический), лучшая форма: '__local float localBuffer [1024];' r чем использование аргумента ядра. – Dithermaster

+0

Массив l_data - это точный размер LOCAL_MEM_SIZE, возвращаемый GetDeviceInfo. В этом случае это 32768, и это число, которое я передаю clSetKernelArg. Аргумент указателя для clSetKernelArg равен NULL, и я собираюсь сыграть с этим прямо сейчас, чтобы узнать, не является ли это проблемой. Локальная память динамическая, не фиксированная, поскольку я использую всю локальную память, доступную для устройства, но я буду искать способ сделать это изнутри ядра. – Chris

+0

Игнорируйте то, что я сказал об аргументе NULL выше, я узнал, что так оно и должно быть. Я обнаружил, что в самом маленьком случае l_addr никогда не превышает 'get_local_id (0)'. Поскольку количество рабочих элементов на группу намного меньше, чем LOCAL_MEM_SIZE, я не могу понять, к чему обращается доступ к 'l_data [l_addr + 3]' за концом массива. – Chris

ответ

0

Я не совсем уверен, почему он работает, но мне удалось найти решение. С этой программой размер рабочей группы должен был быть 1024. Две карты NVIDIA уже имели это как максимальный размер рабочей группы, но у процессора Intel был максимальный размер рабочей группы 4096 (оба были возвращены clGetKernelWorkGroupInfo(...CL_KERNEL_WORK_GROUP_SIZE...). Вот почему графические процессоры работал и процессор не сделал.

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

Смежные вопросы