Для генерации кода графического процессора основным механизмом создания ядер 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 не является параллелизуемым. При выполнении анализа цикла для создания ядер графический процессор 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
При извлечении ядра используется анализ зависимости от параллельного цикла. Есть случаи, когда анализ зависимости цикла не может обнаружить параллель для цикла. coder.gpu.kernel позволяет кодеру графического процессора переопределять анализ зависимости и принудительно создавать ядро. Предостережение заключается в том, чтобы пользователь был уверен, что цикл является циклом «для всех» без межитерационных зависимостей.
Использовать coder.gpu.kernel pragma явно на каждом из циклов for.
Кодер графического процессора не может создавать ядра, если для доступа к элементам массива используется логическое индексирование.
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.
Если меньшие петли в гнезде цикла являются внешними наибольшими петлями, то ядро может быть создано только с подмножеством петель во вложении. Если алгоритм позволяет, всегда помещайте наибольшие петли в самое внешнее вложение.
Перезаписать вложенность цикла с более крупными контурами в качестве внешних контуров.