Какова лучшая компьютерная практика общего назначения в OpenCL для итерационных задач?
Когда у нас есть программа, которая требует большого количества операций над большими наборами данных, и операции над каждым из элементов данных независимы, OpenCL может быть одним из лучших способов сделать это быстрее. У меня есть программа, подобная следующей:
while( function(b,c)!=TRUE)
{
[X,Y] = function1(BigData);
M = functionA(X);
b = function2(M);
N = functionB(Y);
c = function3(N);
}
Здесь функция1 применяется к каждому из элементов BigData и создает еще два больших набора данных (X,Y). function2 и function3 затем применяются операции индивидуально для каждого из элементов в этих данных X, Y, соответственно.
Поскольку операции всех функций применяются к каждому из элементов наборов данных независимо, использование графического процессора может сделать это быстрее. Поэтому я придумываю следующее:
while( function(b,c)!=TRUE)
{
//[X,Y] = function1(BigData);
1. load kernel1 and BigData on the GPU. each of the thread will work on one of the data
element and save the result on X and Y on GPU.
//M = functionA(X);
2a. load kernel2 on GPU. Each of the threads will work on one of the
data elements of X and save the result on M on GPU.
(workItems=n1, workgroup size=y1)
//b = function2(M);
2b. load kernel2 (Same kernel) on GPU. Each of the threads will work on
one of the data elements of M and save the result on B on GPU
(workItems=n2, workgroup size=y2)
3. read the data B on host variable b
//N = functionB(Y);
4a. load kernel3 on GPU. Each of the threads will work on one of the
data element of Y and save the result on N on GPU.
(workItems=n1, workgroup size=y1)
//c = function2(M);
4b. load kernel3 (Same kernel) on GPU. Each of the threads will work
on one of the data element of M and save the result on C on GPU
(workItems=n2, workgroup size=y2)
5. read the data C on host variable c
}
Тем не менее, накладные расходы, связанные с этим кодом, кажутся мне значительными (я реализовал тестовую программу и запустил ее на GPU). И если ядра имеют какую-то синхронизацию, это может привести к большему замедлению.
Я также считаю, что рабочий процесс довольно распространен. Так что лучше всего использовать OpenCL для ускорения для такой программы.
1 ответ
Я не думаю, что есть общая проблема с тем, как вы разделили проблему на ядра, хотя трудно сказать, потому что вы не очень конкретны. Как часто вы ожидаете запуска цикла while?
Если ваши ядра выполняют незначительную работу, но внешний цикл выполняет много итераций, вы можете объединить ядра в одно и выполнить некоторое количество итераций внутри самого ядра, если это работает для вашей проблемы.
Иначе:
Если вы получаете неожиданно плохую производительность, вам, скорее всего, нужно следить за эффективностью каждого из ваших ядер и, возможно, их схемами доступа к данным. Если соседние рабочие элементы не читают / записывают соседние данные (в идеале: 16 рабочих элементов читают по 4 байта каждый из строки кэша по 64 байта за раз), вы, вероятно, теряете пропускную способность памяти. Если в ваших ядрах много условных или непостоянных итераций цикла, это будет стоить вам и т. Д.
Вы не указываете, какое время выполнения вы получаете, на какой размер задания (Десятки? Тысячи? Миллионы арифметических операций? Насколько велики ваши наборы данных?) Или на каком оборудовании. (Вычислительная карта? Ноутбук IGPU?) "Значительные накладные расходы" могут означать много разных вещей. 5ms? 1 секунда?
Intel, nVidia и AMD публикуют руководства по оптимизации - вы читали их?