В этом примере показано, как использовать Coder™ графического процессора для использования библиотеки CUDA ® Fast Fourier Transform (cuFFT) для вычисления двухмерного FFT на графическом процессоре NVIDIA ®. Двумерное преобразование Фурье используется в оптике для вычисления дифракционных диаграмм дальнего поля. Когда монохроматический источник света проходит через небольшую апертуру, как, например, в эксперименте Янга с двойной щелью, можно наблюдать эти дифракционные картины. В этом примере также показано, как использовать указатели графического процессора в качестве входных данных для функции начального уровня при создании CUDA MEX, исходного кода, статических библиотек, динамических библиотек и исполняемых файлов. Благодаря использованию этой функциональности производительность генерируемого кода повышается за счет минимизации количества вызовов cudaMemcpy в генерируемом коде.
Необходимый
В этом примере создается CUDA MEX со следующими требованиями сторонних производителей.
CUDA поддерживает графический процессор NVIDIA и совместимый драйвер.
Дополнительный
Для построений, отличных от MEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.
Инструментарий NVIDIA.
Переменные среды для компиляторов и библиотек. Дополнительные сведения см. в разделах Аппаратное обеспечение сторонних производителей и Настройка необходимых продуктов.
Чтобы убедиться, что компиляторы и библиотеки, необходимые для выполнения этого примера, настроены правильно, используйте coder.checkGpuInstall функция.
envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);
Перед моделированием света, прошедшего через апертуру, необходимо определить систему координат. Получение правильного числового поведения при вызове fft2, вы должны тщательно организовать
и
так, чтобы нулевое значение было в правильном месте. N2 равна половине размера в каждом измерении.
N2 = 1024; [gx, gy] = meshgrid(-1:1/N2:(N2-1)/N2);
Имитировать эффект прохождения параллельного луча монохроматического света через небольшую прямоугольную апертуру. Двумерное преобразование Фурье описывает световое поле на большом расстоянии от апертуры. Форма aperture как логическая маска, основанная на системе координат. Источник света представляет собой вариант апертуры с двойной точностью. Найдите световой сигнал дальнего поля с помощью fft2 функция.
aperture = (abs(gx) < 4/N2) .* (abs(gy) < 2/N2); lightsource = double(aperture); farfieldsignal = fft2(lightsource);
visualize.m функция отображает интенсивность света для прямоугольной апертуры. Вычислите интенсивность света в дальнем поле по величине в квадрате светового поля. Для облегчения визуализации используйте fftshift функция.
type visualize
function visualize(farfieldsignal, titleStr) farfieldintensity = real( farfieldsignal .* conj( farfieldsignal ) ); imagesc( fftshift( farfieldintensity ) ); axis( 'equal' ); axis( 'off' ); title(titleStr); end
str = sprintf('Rectangular Aperture Far-Field Diffraction Pattern in MATLAB');
visualize(farfieldsignal,str);

Создавать функцию точки входа не требуется. Можно непосредственно создать код для MATLAB ®fft2 функция. Создание CUDA MEX для MATLAB fft2 , в объекте конфигурации установите EnablecuFFT и использовать codegen функция. Кодер графического процессора заменяет fft, ifft, fft2, ifft2, fftn, и ifftn вызовы функций в коде MATLAB для соответствующих вызовов библиотеки cuFFT. Для двумерных преобразований и выше кодер GPU создает несколько 1-D пакетных преобразований. Эти пакетные преобразования имеют более высокую производительность, чем единичные преобразования. После генерации функции MEX можно проверить, что она обладает теми же функциями, что и исходная функция начального уровня MATLAB. Выполнить сгенерированное fft2_mex и постройте график результатов.
cfg = coder.gpuConfig('mex'); cfg.GpuConfig.EnableCUFFT = 1; codegen -config cfg -args {lightsource} fft2 farfieldsignalGPU = fft2_mex(lightsource); str = sprintf('Rectangular Aperture Far-Field Diffraction Pattern on GPU'); visualize(farfieldsignalGPU,str);
Code generation successful.

Двухщелевой эксперимент Янга показывает световую интерференцию, когда апертура содержит две параллельные щели. Виден ряд ярких точек, где происходит конструктивное пересечение. В этом случае образуют отверстие, представляющее две щели. Ограничьте отверстие в
направлении, чтобы гарантировать, что результирующий рисунок не будет полностью сконцентрирован вдоль горизонтальной оси.
slits = (abs(gx) <= 10/N2) .* (abs(gx) >= 8/N2); aperture = slits .* (abs(gy) < 20/N2); lightsource = double(aperture);
Поскольку размер, тип и сложность входных данных остаются прежними, повторно используйте fft2_mex сгенерированная MEX-функция и отображение интенсивности, как и ранее.
farfieldsignalGPU = fft2_mex(lightsource);
str = sprintf('Double Slit Far-Field Diffraction Pattern on GPU');
visualize(farfieldsignalGPU,str);

В CUDA MEX, сгенерированном выше, входные данные, поступающие в MEX, копируются из CPU в память GPU, вычисления выполняются на GPU и результат копируется обратно в CPU. Альтернативно, код CUDA может быть сгенерирован таким образом, что он принимает указатели GPU непосредственно. Для целей MEX указатели GPU могут передаваться из MATLAB ® в CUDA MEX с помощьюgpuArray. Для других целей необходимо выделить память GPU и скопировать входы из CPU в GPU внутри рукописной основной функции, прежде чем они будут переданы функции точки входа.
lightsource_gpu = gpuArray(lightsource); cfg = coder.gpuConfig('mex'); cfg.GpuConfig.EnableCUFFT = 1; codegen -config cfg -args {lightsource_gpu} fft2 -o fft2_gpu_mex
Code generation successful.
Только числовые и логические типы входных матриц могут передаваться как указатели GPU в функцию точки входа. Другие типы данных, которые не поддерживаются, могут передаваться в качестве входов ЦП. Во время генерации кода, если, по меньшей мере, один из входов, предоставляемых функции точки входа, является указателем GPU, выходы, возвращаемые от функции, также являются указателями GPU. Однако если тип данных вывода не поддерживается как указатель графического процессора, например структура или массив ячеек, вывод будет возвращен как указатель CPU. Дополнительные сведения о передаче указателей GPU функции точки входа см. в разделе Поддержка массивов GPU.
Обратите внимание на разницу в сгенерированном коде CUDA при использовании lightsource_gpu Вход графического процессора. Это позволяет избежать копирования входных данных из CPU в память GPU и обратного копирования результата из GPU в память CPU. Это приводит к меньшему количеству cudaMemcpys и повышает производительность генерируемого CUDA MEX.
Проверка того, что сгенерированный CUDA MEX использует gpuArray имеет ту же функциональность, выполните сгенерированный fft2_gpu_mexсоберите результаты на основе и постройте график результатов.
farfieldsignal_gpu = fft2_gpu_mex(lightsource_gpu);
farfieldsignal_cpu = gather(farfieldsignal_gpu);
str = sprintf('Double Slit Far-Field Diffraction Pattern on GPU using gpuArray');
visualize(farfieldsignal_cpu,str);

codegen | coder.checkGpuInstall | coder.gpu.constantMemory | coder.gpu.kernel | coder.gpu.kernelfun | gpucoder.matrixMatrixKernel | gpucoder.stencilKernel