2016-12-15 2 views
0

Я использую OpenCL (Xcode, Intel GPU), и я пытаюсь реализовать ядро, которое вычисляет скользящие средние и отклонения. Я хочу передать в ядро ​​несколько двойных массивов различной длины. Возможно ли это реализовать, или мне нужно заполнить меньшие массивы нулями, чтобы все массивы имели одинаковый размер?Вычисление на массивах переменной длины в OpenCL

Я новичок в OpenCL и GPGPU, поэтому, пожалуйста, простите мое незнание любой номенклатуры.

ответ

2

Вы можете передать в ядро ​​любой буфер, ядру не нужно его использовать. Например, если ваше ядро ​​сокращает буфер, во время выполнения вы можете запросить количество рабочих элементов (предметов для уменьшения) с помощью get_global_size(0). Затем вызовите ядро ​​с соответствующими параметрами.

Пример (неоптимизированная):

__kernel reduce_step(__global float* data) 
{ 
    int id = get_global_id(0); 
    int size = get_global_size(0); 
    int size2 = size/2; 
    int size2p = (size+1)/2; 
    if(id<size2) //Only reduce up to size2, the odd element will remain in place 
     data[id] += data[id+size2p]; 
} 

Тогда вы можете назвать это так.

void reduce_me(std::vector<cl_float>& data){ 
    size_t size = data.size(); 

    //Copy to a buffer already created, equal or bigger size than data size 
    // ... TODO, check sizes of buffer or change the buffer set to the kernel args. 
    queue.enqueueWriteBuffer(buffer,CL_FALSE,0,sizeof(cl_float)*size,data.data()); 

    //Reduce until 1024 
    while(size > 1024){ 
     queue.enqueueNDRangeKernel(reduce_kernel,cl::NullRange,cl::NDRange(size),cl::NullRange); 
     size /= 2; 
    } 

    //Read out and trim 
    queue.enqueueReadBuffer(buffer,CL_TRUE,0,sizeof(cl_float)*size,data.data()); 
    data.resize(size); 
} 
+0

так я не могу легко сказать от Хроноса спецификации, но делает 'get_global_size (п)' получить элемент п от 'globalWorkSize []'? И как вы используете функцию get_global_size() для выполнения разных задач? Любые обучающие материалы или примеры, которые вы знаете, которые могли бы помочь. Моей идеальной ситуацией было бы передать большую константу массивов, каждая из которых содержит массивы переменной длины. У меня возникла идея стандартизировать длину массивов путем заполнения нулями и свернуть его в один чрезвычайно большой массив, а затем использовать модуль оператора в ядре для получения изменений в массивах. Но это кажется дорогим для памяти? Спасибо – Zroach

+0

Вам не нужно передавать все данные в одном массиве, если вы можете их разделить в разные массивы. Если вам нужно выполнить различную работу на разных массивах, отделите их в разных ядрах. Передача 20 буферов с 20 различными длинами, чтобы выполнить 20 различных процессов в одном ядре, не только трудно сделать, но и неоптимально, так как у вас будет много кодовых путей для ее достижения. Что я изображаю в своем коде, является примером ядра, которое выполняет процесс в буфере, размер которого известен во время выполнения и не существует ветвления. – DarkZeros

+0

Ну, я делаю скользящие средние/отклонения на 5 разных периодов времени, вероятно, около миллиарда точек данных. Я пытался придумать некоторые умные способы избежать необходимости вызывать ядро ​​для каждой точки данных (поскольку средние значения основаны на предыдущих точках данных), так как я уверен, что у этого есть приличная накладная цена. Как я уже сказал, моя мысль заключалась в том, чтобы свести несколько примеров в разные массивы временных периодов, а затем выполнить с помощью целочисленного div. Я проверю производительность. Также думал, что я могу что-то сделать с рабочими группами/измерениями/независимо, но я еще недостаточно образован – Zroach

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