Для генерации кода графического процессора, первичного механизма для создания 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
является большим (итерация), затем лучшая эффективность может быть достигнута путем создания ядер для самого внутреннего цикла.
Существует три пути, которыми можно параллелизировать самый внутренний цикл:
Перепишите код так, чтобы самый внутренний сегмент кода не был во вложенном цикле.
Если размер итерации внешнего контура мал, то присоедините цикл к a 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.
Если меньшие циклы во вложенном множестве цикла являются внешним большинство циклов, то ядро могло быть создано с только подмножеством циклов во вложении. Если алгоритм позволяет его, всегда помещайте самые большие циклы в наиболее удаленное вложение.
Перепишите вложение цикла с большими циклами как внешние контуры.