Этот пример показывает, как сгенерировать автономный код (статическая библиотека, динамически подключаемая библиотека или исполняемая программа), который синхронизирует многопоточный доступ к процессу планирования FFTW.
Генератор кода производит вызовы библиотеки FFTW, когда все эти условия верны:
Ваш код MATLAB® вызывает один из этих functions:fft, fft2, fftn, ifft, ifft2 или ifftn.
Вы генерируете автономный код C/C++.
У вас есть доступ к установке библиотеки FFTW, версии 3.2 или позже.
Вы задаете установку библиотеки FFTW в классе обратного вызова библиотеки FFT, который выводит от coder.fftw.StandaloneFFTW3Interface.
Вы устанавливаете параметр конфигурации CustomFFTCallback на имя класса обратного вызова. В приложении MATLAB Coder™ используйте установку обратного вызова библиотеки Custom FFT.
Если несколько потоков вызывают библиотеку FFTW, то сгенерированный код должен предотвратить параллельный доступ к процессу планирования FFTW. Чтобы синхронизировать доступ к планированию FFTW, в вашем классе обратного вызова библиотеки FFT, реализуют методы unlock и lock. Необходимо также обеспечить код С, который управляет блокировкой или взаимным исключением. Многие библиотеки, такие как OpenMP, pthreads, и библиотека стандарта C++ (C++ 11 и позже) обеспечивают блокировки. Этот пример показывает, как реализовать lock и методы unlock и обеспечить код С поддержки. Чтобы управлять блокировкой, этот пример пользуется библиотекой OpenMP.
Прежде чем вы запустите для основного рабочего процесса для генерации вызовов библиотеки FFTW в автономном коде, смотрите, Ускоряют Быстрые преобразования Фурье в Сгенерированном Автономном Коде при помощи Вызовов Библиотеки FFTW.
Вы должны иметь:
Доступ к установленной библиотеке FFTW.
Компилятор, который поддерживает библиотеку OpenMP. Чтобы пользоваться различной библиотекой, такой как pthreads, изменяют код С поддержки соответственно.
Запишите функции MATLAB mycustomfft, который вызывает функцию быстрого преобразования Фурье в цикле parfor:
function y = mycustomfft() %#codegen t = 0:1/50:10-1/50; x = sin(2*pi*15*t) + sin(2*pi*20*t); y = fft(x); parfor k = 1:100 y = y + ifft(x+k); end
Запишите функции C, которые инициализируют, устанавливают и сбрасывают блокировку. Этот пример пользуется библиотекой OpenMP, чтобы управлять блокировкой. Для различной библиотеки измените код соответственно.
Создайте файл mylock.c, который содержит этот код С:
#include "mylock.h"
#include "omp.h"
static omp_nest_lock_t lockVar;
void mylock_initialize(void)
{
omp_init_nest_lock(&lockVar);
}
void mylock(void)
{
omp_set_nest_lock(&lockVar);
}
void myunlock(void)
{
omp_unset_nest_lock(&lockVar);
}
Создайте заголовочный файл mylock.h, который содержит:
#ifndef MYLOCK_H #define MYLOCK_H void mylock_initialize(void); void mylock(void); void myunlock(void); #endif
Запишите классу обратного вызова БПФа myfftcb что:
Задает библиотеку FFTW.
lock реализаций и методы unlock, которые вызывают код С поддержки, чтобы управлять доступом к планированию FFTW.
Используйте этот класс в качестве шаблона. Замените fftwLocation на местоположение вашей установки библиотеки FFTW.
classdef myfftcb < coder.fftw.StandaloneFFTW3Interface methods (Static) function th = getNumThreads coder.inline('always'); th = int32(coder.const(1)); end function lock() coder.cinclude('mylock.h', 'InAllSourceFiles', true); coder.inline('always'); coder.ceval('mylock'); end function unlock() coder.cinclude('mylock.h', 'InAllSourceFiles', true); coder.inline('always'); coder.ceval('myunlock'); end function updateBuildInfo(buildInfo, ctx) fftwLocation = '\usr\lib\fftw'; includePath = fullfile(fftwLocation, 'include'); buildInfo.addIncludePaths(includePath); libPath = fullfile(fftwLocation, 'lib'); %Double libName1 = 'libfftw3-3'; [~, libExt] = ctx.getStdLibInfo(); libName1 = [libName1 libExt]; addLinkObjects(buildInfo, libName1, libPath, 1000, true, true); %Single libName2 = 'libfftw3f-3'; [~, libExt] = ctx.getStdLibInfo(); libName2 = [libName2 libExt]; addLinkObjects(buildInfo, libName2, libPath, 1000, true, true); end end end
Создайте объект настройки генерации кода для генерации динамически подключаемой библиотеки.
cfg = coder.config('dll');Сконфигурируйте генерацию кода, чтобы использовать класс обратного вызова БПФа myfftcb.
cfg.CustomFFTCallback = 'myfftcb';
Включайте код С поддержки в сборку.
cfg.CustomSource = 'mylock.c';Сгенерируйте вызов функции инициализации блокировки в коде инициализации.
cfg.CustomInitializer = 'mylock_initialize();';Сгенерируйте библиотеку.
codegen -config cfg mycustomfft -report
EnableOpenMP должен быть true, или необходимо вручную передать флаги OpenMP компилятору. По умолчанию параметром EnableOpenMP является true.
Для предыдущего примера в приложении MATLAB CODER используйте эти настройки проекта:
Чтобы задать класс обратного вызова библиотеки FFT, установите обратный вызов библиотеки Custom FFT на myfftcb.
Чтобы задать код С, чтобы включать, установите Дополнительные исходные файлы на mylock.c c.
Чтобы задать генерацию вызова mylock_initialize в коде инициализации, установите, Инициализируют функцию к mylock_initialize();.
coder.ceval | coder.fftw.StandaloneFFTW3Interface