В этом примере показано, как использовать GPU Coder™, чтобы усилить библиотеку CUDA® Fast Fourier Transform (cuFFT), чтобы вычислить двумерный БПФ на графическом процессоре NVIDIA®. Двумерное преобразование Фурье используется в оптике, чтобы вычислить шаблоны дифракции далекого поля. Когда монохроматический источник света проходит через маленькую апертуру, такой как в эксперименте двойного разреза Янга, можно наблюдать эти дифракционные шаблоны. Этот пример также показывает вам, как использовать указатели графического процессора в качестве входных параметров к функции точки входа при генерации MEX CUDA, исходного кода, статических библиотек, динамических библиотек и исполняемых файлов. При помощи этой функциональности производительность сгенерированного кода улучшается путем минимизации количества вызовов cudaMemcpy в сгенерированном коде.
Необходимый
Этот пример генерирует MEX CUDA и имеет следующие сторонние требования.
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
функция. Сгенерировать MEX CUDA для fft2
MATLAB функция, в объекте настройки, установила
EnablecuFFT
свойство и использование codegen
функция. GPU Coder заменяет fft
ifft
fft2
ifft2
fftn
, и ifftn
вызовы функции в вашем коде MATLAB к соответствующим cuFFT вызовам библиотеки. Для двумерных преобразований и выше, GPU Coder создает несколько 1D пакетных преобразований. Эти пакетные преобразования имеют более высокую эффективность, чем одно преобразования. После генерации 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);
В MEX CUDA, сгенерированном выше, вход, предоставленный MEX, копируется от центрального процессора до памяти графического процессора, расчет выполняется на графическом процессоре, и результат копируется назад в центральный процессор. В качестве альтернативы код CUDA может быть сгенерирован таким образом, что он принимает указатели графического процессора непосредственно. Для целей MEX указатели графического процессора могут быть переданы от MATLAB® до MEX CUDA с помощью gpuArray
. Для других целей должна быть выделена память графического процессора, и входные параметры должны быть скопированы с центрального процессора на графический процессор в рукописной основной функции, прежде чем они будут переданы функции точки входа.
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.
Только числовые и логические входные матричные типы могут быть переданы как указатели графического процессора на функцию точки входа. Другие типы данных, которые не поддерживаются, могут быть переданы как входные параметры центрального процессора. Во время генерации кода, если по крайней мере одни из входных параметров, предоставленных функции точки входа, являются указателем графического процессора, выходные параметры, возвращенные функции, являются также указателями графического процессора. Однако, если тип данных выхода не поддержится как указатель графического процессора, такой как struct или массив ячеек, выходной параметр будет возвращен как указатель центрального процессора. Для получения дополнительной информации о передающих указателях графического процессора на функцию точки входа смотрите Поддержку Массивов графического процессора.
Заметьте различие в сгенерированном коде CUDA при использовании lightsource_gpu
Вход GPU. Это старается не копировать вход от центрального процессора до памяти графического процессора и старается не копировать результат назад с графического процессора на память ЦП. Это приводит к меньшему количеству cudaMemcpys
и улучшает производительность сгенерированного MEX CUDA.
Проверять что сгенерированный MEX CUDA с помощью 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