Симулируйте дифракционные шаблоны Используя библиотеки БПФ CUDA

В этом примере показано, как использовать GPU Coder™, чтобы усилить библиотеку CUDA® Fast Fourier Transform (cuFFT), чтобы вычислить двумерный БПФ на графическом процессоре NVIDIA®. Двумерное преобразование Фурье используется в оптике, чтобы вычислить шаблоны дифракции далекого поля. Когда монохроматический источник света проходит через маленькую апертуру, такой как в эксперименте двойного разреза Янга, можно наблюдать эти дифракционные шаблоны. Этот пример также показывает вам, как использовать указатели графического процессора в качестве входных параметров к функции точки входа при генерации MEX CUDA, исходного кода, статических библиотек, динамических библиотек и исполняемых файлов. При помощи этой функциональности производительность сгенерированного кода улучшается путем минимизации количества вызовов cudaMemcpy в сгенерированном коде.

Сторонние необходимые условия

Необходимый

Этот пример генерирует MEX CUDA и имеет следующие сторонние требования.

  • CUDA включил NVIDIA графический процессор и совместимый драйвер.

Дополнительный

Для сборок неMEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.

Проверьте среду графического процессора

Чтобы проверить, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно, используйте coder.checkGpuInstall функция.

envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

Задайте систему координат

Прежде, чем симулировать свет, который прошел через апертуру, необходимо задать систему координат. Получить правильное числовое поведение, когда вы вызываете fft2, необходимо тщательно расположить$x$ и$y$ так, чтобы нулевое значение было в правильном месте. 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);

Сгенерируйте MEX CUDA для функции

Вы не должны создавать функцию точки входа. Можно непосредственно сгенерировать код для MATLAB® fft2 функция. Сгенерировать MEX CUDA для fft2 MATLAB функция, в объекте настройки, установила EnablecuFFT свойство и использование codegen функция. GPU Coder заменяет fftifftfft2ifft2fftn, и 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);

Симулируйте эксперимент Двойного Разреза молодежи

Эксперимент двойного разреза молодежи показывает легкую интерференцию, когда апертура включает два параллельных разреза. Серия ярких точек отображается, где конструктивная интерференция происходит. В этом случае сформируйте апертуру, представляющую два разреза. Ограничьте апертуру в$y$ направлении, чтобы гарантировать, что получившийся шаблон не полностью сконцентрирован вдоль горизонтальной оси.

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, копируется от центрального процессора до памяти графического процессора, расчет выполняется на графическом процессоре, и результат копируется назад в центральный процессор. В качестве альтернативы код 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

Только числовые и логические входные матричные типы могут быть переданы как указатели графического процессора на функцию точки входа. Другие типы данных, которые не поддерживаются, могут быть переданы как входные параметры центрального процессора. Во время генерации кода, если по крайней мере одни из входных параметров, предоставленных функции точки входа, являются указателем графического процессора, выходные параметры, возвращенные функции, являются также указателями графического процессора. Однако, если тип данных выхода не поддержится как указатель графического процессора, такой как struct или массив ячеек, выходной параметр будет возвращен как указатель центрального процессора. Для получения дополнительной информации о передающих указателях графического процессора на функцию точки входа смотрите Поддержку Массивов графического процессора.

Заметьте различие в сгенерированном коде CUDA при использовании lightsource_gpu Вход GPU. Это старается не копировать вход от центрального процессора до памяти графического процессора и старается не копировать результат назад с графического процессора на память ЦП. Это приводит к меньшему количеству cudaMemcpys и улучшает производительность сгенерированного MEX CUDA.

Проверьте результаты 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);