Сгенерируйте код С из кода MATLAB

MATLAB® Coder™ генерирует высоко оптимизированный ANSI C и Код С++ от функций и Системных объектов в Communications Toolbox™. Можно развернуть этот код в большом разнообразии приложений. Рабочий процесс, описанный в этой теме, использует функции DSP System Toolbox™, но тот же рабочий процесс запрашивает Communications Toolbox.

Этот пример генерирует код С от Построения Синусоидальный Сигнал Используя Высокий энергетический Содействующий пример БПФ и создает исполняемый файл из сгенерированного кода.

Вот код MATLAB для этого примера:

L = 1020;
Sineobject = dsp.SineWave('SamplesPerFrame',L,...  
'PhaseOffset',10,'SampleRate',44100,'Frequency',1000);
ft = dsp.FFT('FFTImplementation','FFTW');
ift = dsp.IFFT('FFTImplementation','FFTW','ConjugateSymmetricInput',true);
rng(1);
numIter = 1000;
for Iter = 1:numIter
    Sinewave1 = Sineobject();
    Input = Sinewave1 + 0.01*randn(size(Sinewave1));
    FFTCoeff = ft(Input);
    FFTCoeffMagSq = abs(FFTCoeff).^2;
    
    EnergyFreqDomain = (1/L)*sum(FFTCoeffMagSq);
    [FFTCoeffSorted, ind] = sort(((1/L)*FFTCoeffMagSq),1,'descend');
    
    CumFFTCoeffs = cumsum(FFTCoeffSorted);
    EnergyPercent = (CumFFTCoeffs/EnergyFreqDomain)*100;
    Vec = find(EnergyPercent > 99.99);
    FFTCoeffsModified = zeros(L,1);
    FFTCoeffsModified(ind(1:Vec(1))) = FFTCoeff(ind(1:Vec(1)));
    ReconstrSignal = ift(FFTCoeffsModified);
end
max(abs(Input-ReconstrSignal))
plot(Input,'*');
hold on;
plot(ReconstrSignal,'o');
hold off;

Можно запустить сгенерированный исполняемый файл в среде MATLAB. Кроме того, можно группировать и переместить код к другой среде разработки, которой не установили MATLAB. Можно сгенерировать код с помощью приложения MATLAB Coder или codegen (MATLAB Coder) функция. Этот пример показывает вам рабочий процесс с помощью codegen функция. Для получения дополнительной информации о рабочем процессе приложения смотрите, Генерируют код С при помощи Приложения MATLAB Coder (MATLAB Coder).

Настройте компилятор

Первый шаг должен настроить поддерживаемый компилятор C. MATLAB Coder автоматически определяет местоположение и использует поддерживаемый установленный компилятор. Можно изменить использование компилятора по умолчанию mex -setup. Для получения дополнительной информации см. Компилятор Значения по умолчанию Изменения. Для текущего списка поддерживаемых компиляторов см. Поддерживаемые и Совместимые Компиляторы.

Вспыхните вычислительная часть алгоритма в функцию MATLAB

Чтобы сгенерировать код С, точка входа должна быть функцией. Вы не должны генерировать код для целого приложения MATLAB. Если у вас есть определенные фрагменты, которые в вычислительном отношении интенсивны, генерируют код от этих фрагментов для того, чтобы ускорить ваш алгоритм. Обвязка или драйвер, который вызывает эту функцию MATLAB, не должны генерировать код. Запуски обвязки в MATLAB и могут содержать визуализацию и другие инструменты верификации, которые не являются на самом деле частью системы под тестом. Например, в Построении Синусоидальный Сигнал Используя Высокий энергетический Содействующий пример БПФ, plot функции строят входной сигнал и восстановленный сигнал. plot не поддерживается для генерации кода и должен остаться в обвязке. Чтобы сгенерировать код от обвязки, которая содержит инструменты визуализации, перепишите обвязку как функцию и объявите функции визуализации как внешнее использование функций coder.extrinsic (MATLAB Coder). Чтобы запустить сгенерированный код, который содержит внешние функции, необходимо было установить MATLAB на машине.

Код MATLAB в for цикл, который восстанавливает исходный сигнал с помощью высокоэнергетических коэффициентов БПФ, является в вычислительном отношении интенсивным фрагментом этого алгоритма. Убыстритесь for цикл путем перемещения этой вычислительной части в собственную функцию, GenerateSignalWithHighEnergyFFTCoeffs.m.

L = 1020;
Sineobject = dsp.SineWave('SamplesPerFrame',L,...
    'SampleRate',44100,'Frequency',1000);
rng(1);
numIter = 1000;
for Iter = 1:numIter
    Sinewave1 = Sineobject();
    Input = Sinewave1 + 0.01*randn(size(Sinewave1));
    [ReconstrSignal,numCoeff] = GenerateSignalWithHighEnergyFFTCoeffs(Input);
end
max(abs(Input-ReconstrSignal))
figure(1);
plot(Input)
hold on;
plot(ReconstrSignal,'*')
hold off
function [ReconstrSignal,numCoeff] = GenerateSignalWithHighEnergyFFTCoeffs(Input)

ft = dsp.FFT('FFTImplementation','FFTW');
ift = dsp.IFFT('FFTImplementation','FFTW','ConjugateSymmetricInput',true);

FFTCoeff = ft(Input);
FFTCoeffMagSq = abs(FFTCoeff).^2;
L = size(Input,1);
EnergyF = (1/L)*sum(FFTCoeffMagSq);
[FFTCoeffSorted, ind] = sort(((1/L)*FFTCoeffMagSq),1,'descend');

CumFFTCoeffs = cumsum(FFTCoeffSorted);
EnergyPercent = (CumFFTCoeffs/EnergyF)*100;
Vec = find(EnergyPercent > 99.99);
FFTCoeffsModified = zeros(L,1);
FFTCoeffsModified(ind(1:Vec(1))) = FFTCoeff(ind(1:Vec(1)));
numCoeff = Vec(1);
ReconstrSignal = ift(FFTCoeffsModified);
end

Сделайте код подходящим для генерации кода

Прежде чем вы сгенерируете код, необходимо подготовить код MATLAB к генерации кода.

Проверяйте проблемы во время проектирования

Первый шаг должен устранить неподдерживаемые построения и проверку на любые проблемы генерации кода. Для списка функций Communications Toolbox, поддерживавших MATLAB Coder, смотрите Функции и Системные объекты, Поддержанные для генерации кода C. Для списка поддерживаемых построений языка смотрите Функции языка MATLAB, Поддерживавшие для Генерации кода C/C++ (MATLAB Coder).

Анализатор кода обнаруживает проблемы кодирования во время проектирования, когда вы вводите код. Чтобы включить анализатор кода, необходимо добавить %#codegen прагма к вашему файлу MATLAB.

Инструмент готовности генерации кода экранирует код MATLAB на функции, которые не поддерживаются для генерации кода. Один из способов получить доступ к этому инструменту путем щелчка правой кнопкой по файлу MATLAB в его текущей папке. Работа инструмента генерации кода GenerateSignalWithHighEnergyFFTCoeffs.m не находит проблем.

Проверяйте проблемы во время генерации кода

Прежде чем вы сгенерируете код С, гарантируете, что код MATLAB успешно генерирует MEX-функцию. codegen (MATLAB Coder) команда раньше генерировала MEX-функцию, обнаруживает любые ошибки, которые предотвращают код для того, чтобы подойти для генерации кода.

Запущенный codegen on GenerateSignalWithHighEnergyFFTCoeffs.m функция.

codegen -args {Input} GenerateSignalWithHighEnergyFFTCoeffs 

Следующее сообщение появляется в командной строке MATLAB:

??? The left-hand side has been constrained to be non-complex, but the right-hand side 
is complex. To correct this problem, make the right-hand side real using the function 
REAL, or change the initial assignment to the left-hand side variable to be a complex 
value using the COMPLEX function.

Error in ==> GenerateSignalWithHighEnergy Line: 24 Column: 1
Code generation failed: View Error Report
Error using codegen
 
 

Это сообщение относится к переменной FFTCoeffsModified. Кодер ожидает, что эта переменная будет инициализирована как комплексная переменная. Чтобы решить этот вопрос, инициализируйте FFTCoeffsModified переменная как комплекс.

FFTCoeffsModified = zeros(L,1)+0i;

Повторно выполнитесь codegen функционируйте и вы видите, что файл MEX сгенерирован успешно в текущей папке с .mex расширение.

codegen -args {Input} GenerateSignalWithHighEnergyFFTCoeffs 

Проверяйте проблемы во время выполнения

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

[ReconstrSignal,numCoeff] = GenerateSignalWithHighEnergyFFTCoeffs(Input);
с
[ReconstrSignalMex,numCoeffMex] = GenerateSignalWithHighEnergyFFTCoeffs_mex(Input);
в обвязке.

Обвязка теперь похожа:

L = 1020;
Sineobject = dsp.SineWave('SamplesPerFrame',L,...
    'SampleRate',44100,'Frequency',1000);
rng(1);
numIter = 1000;
for Iter = 1:numIter
    Sinewave1 = Sineobject();
    Input = Sinewave1 + 0.01*randn(size(Sinewave1));
    [ReconstrSignalMex,numCoeffMex] = GenerateSignalWithHighEnergyFFTCoeffs_mex(Input,L);
end
max(abs(Input-ReconstrSignalMex))
figure(1);
plot(Input)
hold on;
plot(ReconstrSignalMex,'*')
hold off

Код запускается успешно, указывая, что нет никаких ошибок времени выполнения.

Сравните MEX-функцию с симуляцией

Заметьте, что обвязка запускается намного быстрее с MEX-функцией по сравнению с регулярной функцией. Причина генерации MEX-функции не только, чтобы обнаружить генерацию кода и проблемы во время выполнения, но также и ускорить определенные части вашего алгоритма. Для примера смотрите Ускорение алгоритма Обработки сигналов в MATLAB.

Необходимо также проверять, что числовой выход следует из MEX и соответствия регулярной функции. Сравните восстановленный сигнал, сгенерированный GenerateSignalWithHighEnergyFFTCoeffs.m функционируйте и его дубликат MEX GenerateSignalWithHighEnergyFFTCoeffs_mex.

max(abs(ReconstrSignal-ReconstrSignalMex))

ans =

     2.2204e-16

Результаты соответствуют очень тесно, подтверждая, что генерация кода успешна.

Сгенерируйте независимый исполняемый файл

Если ваша цель состоит в том, чтобы запустить сгенерированный код в среде MATLAB, вашей целью сборки может только быть MEX-функция. Если развертывание кода к другому приложению является целью, то сгенерируйте независимый исполняемый файл из целого приложения. Для этого обвязка должна быть функцией, которая вызывает подфункцию GenerateSignalWithHighEnergyFFTCoeffs. Перепишите обвязку как функцию.

function reconstructSignalTestbench()
L = 1020;
Sineobject = dsp.SineWave('SamplesPerFrame',L,...
    'SampleRate',44100,'Frequency',1000);
rng(1);
numIter = 1000;
for Iter = 1:numIter
    Sinewave1 = Sineobject();
    Input = Sinewave1 + 0.01*randn(size(Sinewave1));
    [ReconstrSignal,numCoeff] = GenerateSignalWithHighEnergyFFTCoeffs(Input,L);
end

Регистрируйте все 1 000 систем координат входа и восстановленного сигнала, и количество коэффициентов БПФ раньше восстанавливало каждую систему координат сигнала. Запишите все эти данные в двоичный файл под названием data.bin использование dsp.BinaryFileWriter Система object™. Этот пример регистрирует количество коэффициентов, которые являются скалярными значениями как первый элемент каждой системы координат входного сигнала и восстановленного сигнала. Данные, которые будут записаны, имеют формат кадра M = L + 1 и имеют формат, который выглядит так фигура.

N является количеством коэффициентов БПФ, которые представляют 99,99% энергии сигнала текущего входного кадра. Метаданные двоичного файла указывают эту информацию. Выпустите средство записи двоичного файла и закройте двоичный файл в конце.

Обновленная функция обвязки, reconstructSignalTestbench, показан здесь:

function reconstructSignalTestbench()
L = 1020;
Sineobject = dsp.SineWave('SamplesPerFrame',L,...
    'SampleRate',44100,'Frequency',1000);
header = struct('FirstElemInBothCols','Number of Coefficients',...
    'FirstColumn','Input','SecondColumn','ReconstructedSignal');
bfw = dsp.BinaryFileWriter('data.bin','HeaderStructure',header);
numIter = 1000;

M = L+1;
ReSignalAll = zeros(M*numIter,1);
InputAll = zeros(M*numIter,1);
rng(1);

for Iter = 1 : numIter
    Sinewave1 = Sineobject();
    Input = Sinewave1 + 0.01*randn(size(Sinewave1));
    [ReconstrSignal,numCoeffs] = GenerateSignalWithHighEnergyFFTCoeffs(Input);
    InputAll(((Iter-1)*M)+1:Iter*M) = [numCoeffs;Input];
    ReSignalAll(((Iter-1)*M)+1:Iter*M) = [numCoeffs;ReconstrSignal];
end

bfw([InputAll ReSignalAll]);   
release(bfw);

Следующий шаг в генерации исполняемого файла C должен создать a coder.config объект для исполняемого файла и обеспечивает a main.c функционируйте к этому объекту.

cfg =  coder.config('exe');
cfg.CustomSource = 'reconstructSignalTestbench_Main.c';

Вот то, как reconstructSignalTestbench_Main.c функция ищет этот пример.

/*
** reconstructSignalTestbench_main.c
*
* Copyright 2017 The MathWorks, Inc.
*/
#include <stdio.h>
#include <stdlib.h>

#include "reconstructSignalTestbench_initialize.h"
#include "reconstructSignalTestbench.h"
#include "reconstructSignalTestbench_terminate.h"

int main()
{
    reconstructSignalTestbench_initialize();
    reconstructSignalTestbench();    
    reconstructSignalTestbench_terminate();
    
    return 0;
}

Для дополнительных деталей о создании основной функции смотрите Генерирующие Автономные Исполняемые файлы C/C++ из кода MATLAB (MATLAB Coder).

Установите CustomInclude свойство настройки возражает, чтобы задать местоположение основного файла. В этом примере местоположение является текущей папкой.

cfg.CustomInclude = ['"',pwd,'"'];

Сгенерируйте исполняемый файл C путем выполнения следующей команды в командной строке MATLAB:

codegen -config cfg -report reconstructSignalTestbench

MATLAB Coder компилирует и соединяет основную функцию с кодом С, который это генерирует от reconstructSignalTestbench.m.

Если вы используете Windows, вы видите это reconstructSignalTestbench.exe сгенерирован в текущей папке. Если вы используете Linux, сгенерированный исполняемый файл не имеет .exe расширение.

Считайте и проверьте данные о двоичном файле

Выполнение исполняемого файла создает двоичный файл, data.bin, в текущем каталоге и записях вход, восстановленный сигнал и количество коэффициентов БПФ раньше восстанавливали сигнал.

!reconstructSignalTestbench

Можно считать эти данные из двоичного файла с помощью dsp.BinaryFileReader объект. Проверять, что данные записаны правильно, считанные данные из двоичного файла в MATLAB и сравнивают выход с переменными InputAll и ReSignalAll.

Прототип заголовка должен иметь структуру, похожую на структуру заголовка, записанную в файл. Считайте данные как два канала.

M = 1021;
numIter = 1000;
headerPro = struct('FirstElemInBothCols','Number of Coefficients',...
    'FirstColumn','Input','SecondColumn','ReconstructedSignal');
bfr = dsp.BinaryFileReader('data.bin','HeaderStructure',...
headerPro,'SamplesPerFrame',M*numIter,'NumChannels',2);
Data = bfr();

Сравните первый канал с InputAll и второй канал с ReSignalAll.

isequal(InputAll,Data(:,1))
ans =

  logical

   1
isequal(ReSignalAll,Data(:,2))
ans =

  logical

   1

Результаты соответствуют точно, показывая на успешную операцию записи.

Переместите код к другой среде разработки

Если вы генерируете код из своего алгоритма MATLAB, можно переместить код к другой среде разработки, такой как система или интегрированная среда разработки (IDE), которая не включает MATLAB. Можно группировать файлы в сжатый файл с помощью packNGo функция в командной строке или опции Package в приложении MATLAB Coder. Для примера, который иллюстрирует обоих рабочие процессы, см. Код Пакета для Других Сред разработки (MATLAB Coder). Для получения дополнительной информации о packNGo опция, смотрите packNGo в Методах информации о Сборке (MATLAB Coder). Можно переместить и распаковать сжатый zip-файл с помощью стандартной утилиты zip. Для примера о том, как группировать исполняемый файл, сгенерированный в этом примере, смотрите, Перемещают Код, Сгенерированный от кода MATLAB до Другой Среды разработки.

Смотрите также

Функции

Похожие темы

Внешние веб-сайты

Для просмотра документации необходимо авторизоваться на сайте