Для генерации кода графического процессора первичный механизм для создания ядер CUDA® при помощи for
- циклы. Путем вы пишете, что циклы в вашем коде MATLAB® оказывают значительное влияние на количество созданных ядер, а также производительность сгенерированного кода. Когда вы генерируете код графического процессора, проверяйте диагностический отчет видеть, имеет ли ваш сегмент цикла уведомления Loop not parallelized
. Вызовы функций MATLAB в вашем коде могут также иметь for
- циклы, которые содержат эти уведомления. Чтобы получить максимальную производительность, вы хотите гарантировать, что вычисляют интенсивные сегменты цикла в вашем коде, сопоставлены с ядрами и выполнены параллельно. Следующие рекомендации помогают вам в достижении этой цели и генерации эффективных ядер CUDA.
Рассмотрите функцию, которая вложила for
- циклы.
function y = foo(x) ... for i1 = 1:N1 for i2 = 1:N2 for i3 = 1:N3 for i4 = 1:N4 ... end end end end
Примите, что один из промежуточного цикла i3
не parallelizable. Когда выполняет анализ цикла, чтобы создать ядра, GPU Coder™ он считает только наиболее удаленные параллельные циклы i1,i2
и создает ядро с размерностями внешнего цикла N1,N2
. Циклы i3,i4
в теле ядра и выполняется последовательно. Однако, если самый внутренний i4
является большим (итерация), то лучшая производительность может быть достигнута путем создания ядер для самого внутреннего цикла.
Существует три пути, которыми можно параллелизировать самый внутренний цикл:
Перепишите код так, чтобы самый внутренний сегмент кода не был во вложенном цикле.
Если размер итерации внешнего цикла является небольшим, то присоедините цикл к функции coder.unroll
. Эта функция разворачивает for
- цикл путем создания копии тела цикла для каждой итерации цикла. Для получения дополнительной информации смотрите coder.unroll
.
function y = foo(x) ... for i1 = coder.unroll(1:N1) ... end
Сделайте размерность внешнего цикла как динамическую связанной. Таким образом, анализ параллельного цикла перестал работать на внешнем цикле, тогда как это успешно выполняется на внутренних циклах.
function y = foo(x,N1) ... for i1 = 1:N1 ... end
Циклы с пропуском не поддержаны.
while (i < N) ... ... if (cond2) ... ... break; end end
Удалите пропуски путем создания защитной переменной и условного выражения.
cond = true; while (i< N) if(cond) ... ... if(cond2) cond = false; end end end
Экстракция ядра использует анализ зависимости параллельного цикла. Существуют случаи, где анализ зависимости цикла не может обнаружить параллельный цикл for. coder.gpu.kernel
позволяет GPU Coder заменять анализ зависимости и создание ядра силы. Протест для пользователя, чтобы быть уверенным, что цикл “для - весь” цикл без зависимостей межитерации.
Используйте прагму coder.gpu.kernel
явным образом на каждом из ваших циклов for.
GPU Coder не может создать ядра, когда логическая индексация использована для доступа к элементам массива.
i = (mag ~= 0); vx(i) = vx(i)./mag(i); vy(i) = vy(i)./mag(i);
Перепишите код при помощи тела цикла и охраняющий с соответствующим условным выражением.
for i = 1:numel(mag) if (mag(i) ~= 0) vx(i) = vx(i)./mag(i); vy(i) = vy(i)./mag(i); end end
Использование неподдерживаемых функций, прагм кодера, функции тулбокса и т.д. в цикле препятствуют тому, чтобы они стали ядром.
Попытайтесь переписать неподдерживаемые функции с помощью чистого MATLAB.
Если меньшие циклы во вложенном множестве цикла являются внешним большинство циклов, то ядро могло быть создано с только подмножеством циклов во вложении. Если алгоритм позволяет его, всегда помещайте самые большие циклы в наиболее удаленное вложение.
Перепишите вложение цикла с большими циклами как внешние циклы.