主要内容

信号处理算法加速MATLAB

请注意

本例中的基准测试是在具有四个物理内核的机器上进行的。

这个例子展示了如何在MATLAB中加速一个信号处理算法®使用codegen(MATLAB编码器)而且dspunfold功能。您可以从整个MATLAB函数或MATLAB函数的特定部分生成MATLAB可执行程序(MEX函数)。当您运行MEX函数而不是原始的MATLAB代码时,仿真速度可以显著提高。要生成MEX的等效值,算法必须支持代码生成。金宝app

使用codegen(MATLAB编码器),你一定有MATLAB编码器™安装。使用dspunfold,你一定有MATLAB编码器和DSP系统工具箱™安装。

使用dspunfold在Windows和Linux上,必须使用支持开放多处理(Open Multi-Processing, 金宝appOpenMP)应用程序接口的编译器。看到金宝app支持编译器

FIR滤波算法

考虑一个简单的FIR滤波算法来加速。复制firfilter函数代码firfilter.m文件。

函数[y,z1] = firfilter(b,x)%的输入:% b - 1xnaps系数的行向量% x -一帧有噪声的输入%:% z, z1 - NTapsx1状态列向量%输出:% y -过滤输出的帧持续的z;如果(isempty(z)) z = 0(长度(b),1);结束Lx = size(x,1);Y = 0 (size(x),“喜欢”, x);Z1 = z;m = 1:Lx加载下一个输入样本Z1 (1,:) = x(m,:);%计算输出Y (m,:) = b*z1;%更新状态Z1 (2:end,:) = Z1 (1:end-1,:);Z = z1;结束

firfilter函数接受一个滤波器系数向量,b,一个有噪声的输入信号,x,作为输入。方法生成滤波器系数fir1函数。

ntp = 250;Fp = 4e3/(44.1e3/2);b = fir1(ntap -1,Fp);

滤波器对有噪声的正弦波信号流进行滤波firfilter函数。正弦波的帧大小为4000个样本,采样率为192千赫。生成正弦波使用dsp。SineWave系统对象™。噪声是一个均值为0,方差为0.02的白色高斯。命名这个函数firfilter_sim.的firfilter_sim函数调用firfilter函数作用于噪声输入。

函数toval = firfilter_sim(b)%创建信号源Sig = dsp。SineWave (“SamplesPerFrame”, 4000,“SampleRate”, 19200);toval = 0 (4000,500);R = 0.02;清晰的firfilter迭代循环。每次迭代对一帧噪声信号进行滤波。i = 1: 500 trueVal = Sig();原始正弦波百分比noisyVal = trueVal + sqrt(R)*randn;噪声正弦波%filteredVal = firfilter(b,noisyVal);滤过正弦波百分比toval (:,i) = filteredVal;存储整个正弦波结束

运行firfilter_sim并衡量执行的速度。执行速度取决于您的机器。

toval = firfilter_sim(b);t1 = toc;流('原算法模拟时间:%4.1f秒\n', t1);
原算法仿真时间:7.8秒

加速FIR滤波器的使用codegen

调用codegenfirfilter,并生成等价的MEX,firfilter_mex.生成并传递滤波器系数和正弦波信号作为输入firfilter函数。

Ntaps = 250;Sig = dsp。SineWave (“SamplesPerFrame”, 4000,“SampleRate”, 19200);%创建信号源R = 0.02;trueVal = Sig();原始正弦波百分比noisyVal = trueVal + sqrt(R)*randn;噪声正弦波%Fp = 4e3/(44.1e3/2);b = fir1(ntap -1,Fp);%过滤系数codegenfirfilterarg游戏{b, noisyVal}

firfilter_sim函数,取代noisyVal firfilter (b)函数调用noisyVal firfilter_mex (b).命名这个函数firfilter_codegen

函数toval = firfilter_codegen(b)%创建信号源Sig = dsp。SineWave (“SamplesPerFrame”, 4000,“SampleRate”, 19200);toval = 0 (4000,500);R = 0.02;清晰的firfilter_mex迭代循环。每次迭代对一帧噪声信号进行滤波。i = 1: 500 trueVal = Sig();原始正弦波百分比noisyVal = trueVal + sqrt(R)*randn;噪声正弦波%filteredVal = firfilter_mex(b,noisyVal);滤过正弦波百分比toval (:,i) = filteredVal;存储整个正弦波结束

运行firfilter_codegen并衡量执行的速度。执行速度取决于您的机器。

tovalcodegen = firfilter_codegen(b);t2 = toc;流('算法模拟时间与编码:%5f秒\n', t2);流('加速因子与代码:%5f\n'(t1 / t2));
算法仿真时间与编码:0.923683秒加速因子与编码:8.5531

加速增益约为8.5

加速FIR滤波器的使用dspunfold

dspunfold函数生成一个多线程MEX文件,该文件可以进一步提高加速增益。

dspunfold还生成单线程MEX文件和自诊断分析器功能。多线程MEX文件利用主机的多核CPU体系结构。单线程的MEX文件类似于codegen函数生成。分析器函数测量多线程MEX文件相对于单线程MEX文件的加速增益。

调用dspunfoldfirfilter并生成其等价的多线程MEX,firfilter_mt.方法检测样本中的状态长度- f选项,可以进一步提高加速增益。- s汽车触发自动状态长度检测。的详细信息- f而且- s选项,请参阅dspunfold

dspunfoldfirfilterarg游戏{b, noisyVal}- s汽车- f(假,真的)
状态长度:[自动检测]样本,重复:1,输出延迟:8帧,线程:4分析:firfilter。m创建单线程MEX文件:firfilter_st。搜索最小状态长度(这可能需要一些时间)检查无状态…检查4000个样品…检验2000个样品…检验1000个样品…检验500个样品…检验250个样品…125个样品…187个样品…检验218个样品… Insufficient Checking 234 samples ... Insufficient Checking 242 samples ... Insufficient Checking 246 samples ... Insufficient Checking 248 samples ... Insufficient Checking 249 samples ... Sufficient Minimal state length is 249 samples Creating multi-threaded MEX file: firfilter_mt.mexw64 Creating analyzer file: firfilter_analyzer.p

的自动状态长度检测工具检测的确切状态长度259样本。

调用分析器函数并测量多线程MEX文件相对于单线程MEX文件的加速增益。为分析器的每个输入参数提供至少两个不同的帧。帧是沿着第一个维度附加的。分析器在这些帧之间交替,同时验证输出是否匹配。如果不能为每个输入提供多个帧,则会降低分析器的有效性,并可能导致假阳性的验证结果。

firfilter_analyzer ([b; b 0.5 * 0.6 * b], [noisyVal; 0.5 * noisyVal; 0.6 * noisyVal]);
分析多线程MEX文件firfilter_mt.mexw64。为了达到最佳效果,请避免与计算机交互,并在分析仪完成之前停止其他进程。延迟= 8帧加速= 3.2倍

firfilter_mt是否有加速增益因子3.2与单线程MEX文件相比,firfilter_st.要进一步提高速度,请使用- r选择。这样做的代价是输出延迟增加。使用重复因子3..指定确切的状态长度以减少开销并进一步提高速度。

dspunfoldfirfilterarg游戏{b, noisyVal}- s249- f(假,真的)- r3.
状态长度:249个样本,重复:3,输出延迟:24帧,线程:4分析:firfilter。m创建单线程MEX文件:firfilter_st。创建多线程MEX文件:firfilter_mt. txt。mexw64创建分析文件:firfilter_analyzer.p

调用analyzer函数。

firfilter_analyzer ([b; b 0.5 * 0.6 * b], [noisyVal; 0.5 * noisyVal; 0.6 * noisyVal]);
分析多线程MEX文件firfilter_mt.mexw64。为了达到最佳效果,请避免与计算机交互,并在分析仪完成之前停止其他进程。延迟= 24帧加速= 3.8倍

加速增益因子为3.8,或约32倍的执行速度的原始模拟。

对于这个特定的算法,你可以看到dspunfold生成高度优化的代码,而不需要编写任何C或c++代码。加速增益随主机上的核数而增加。

本例中的FIR滤波函数只是一个易于理解的说明性算法。您可以将此工作流应用于任何自定义算法。如果您想使用FIR滤波器,建议您使用dsp。FIRFilterDSP系统工具箱中的系统对象。该对象比本例中给出的基准测试数字运行得快得多,而且不需要生成代码。

卡尔曼滤波算法

考虑一个卡尔曼滤波算法,它估计来自噪声输入的正弦波信号。这个例子展示了卡尔曼滤波器的性能codegen而且dspunfold

噪声正弦波输入帧大小为4000个样本,采样率为192khz。噪声是均值为0,方差为0.02的白色高斯。

这个函数filterNoisySignal调用kalmanfilter函数作用于噪声输入。

类型filterNoisySignal
创建信号源Sig = dsp.SineWave('SamplesPerFrame',4000,'SampleRate',19200);toval = 0 (4000,500);R = 0.02;清楚kalmanfilter;%迭代循环估计正弦波信号i = 1: 500 trueVal = Sig();noisyVal = trueVal + sqrt(R)*randn;%噪声测量estVal = kalmanfilter(noisyVal);卡尔曼滤波估计的正弦波总数val (:,i) = estVal;存储整个正弦波结束
类型kalmanfilter
这个函数使用卡尔曼滤波器跟踪有噪声的正弦信号stateSpaceDim = size(A,1);%测量矩阵H = 1;measurementSpaceDim = size(H,1);numTsteps = size(noisyVal,1)/measurementSpaceDim;用于存储所有时间步长的预测和估计的% ContainersxEstContainer = 0 (size(noisyVal));Q = 0.0001;%过程噪声协方差R = 0.02;%测量噪声协方差持久xhat P xPrior先验; % Local copies of discrete states if isempty(xhat) xhat = 5; % Initial state estimate end if isempty(P) P = 1; % Error covariance estimate end if isempty(xPrior) xPrior = 0; end if isempty(PPrior) PPrior = 0; end % Loop over all time steps for n=1:numTsteps % Gather chunks for current time step zRowIndexChunk = (n-1)*measurementSpaceDim + (1:measurementSpaceDim); stateEstsRowIndexChunk = (n-1)*stateSpaceDim + (1:stateSpaceDim); % Prediction step xPrior = A * xhat; PPrior = A * P * A' + Q; % Correction step. Compute Kalman gain. PpriorH = PPrior * H'; HPpriorHR = H * PpriorH + R; KalmanGain = (HPpriorHR \ PpriorH')'; KH = KalmanGain * H; % States and error covariance are updated in the % correction step xhat = xPrior + KalmanGain * noisyVal(zRowIndexChunk,:) - ... KH * xPrior; P = PPrior - KH * PPrior; % Append estimates xEstContainer(stateEstsRowIndexChunk, :) = xhat; zEstContainer(zRowIndexChunk,:) = H*xhat; end % Populate the outputs estVal = zEstContainer; estState = xEstContainer; end

运行filterNoisySignal.m并衡量执行的速度。

t1 = toc;流('原算法模拟时间:%4.1f秒\n', t1);
原算法仿真时间:21.7秒

加速卡尔曼滤波的使用codegen

调用codegen函数kalmanfilter,并生成等价的MEX,kalmanfilter_mex

kalmanfilter函数要求有噪声的正弦波作为输入。

Sig = dsp。SineWave (“SamplesPerFrame”, 4000,“SampleRate”, 19200);%创建信号源R = 0.02;%测量噪声协方差trueVal =步骤(Sig);%实际值noisyVal = trueVal + sqrt(R)*randn;噪声测量codegenarg游戏{noisyVal}kalmanfilter.m

取代kalmanfilter (noisyVal)filterNoisySignal函数与kalmanfilter_mex (noisyVal).将此函数命名为filterNoisySignal_codegen

函数totVal = filterNoisySignal_codegen%创建信号源Sig = dsp。SineWave (“SamplesPerFrame”, 4000,“SampleRate”, 19200);toval = 0 (4000,500);R = 0.02;清晰的kalmanfilter_mex迭代循环估计正弦波信号i = 1: 500 trueVal = Sig();%实际值noisyVal = trueVal + sqrt(R)*randn;噪声测量estVal = kalmanfilter_mex(noisyVal);用卡尔曼滤波器估计正弦波toval (:,i) = estVal;存储整个正弦波结束

运行filterNoisySignal_codegen并衡量执行的速度。

抽搐;tovalcodegen = filterNoisySignal_codegen;T2 = toc;流('算法模拟时间与编码:%5f秒\n', t2);流(“编码加速%0.1f”、t1 / t2);
使用codegen的算法仿真时间:0.095480秒

卡尔曼滤波算法实现了多次矩阵乘法运算。codegen使用基本线性代数子程序(BLAS)库来执行这些乘法。这些库生成高度优化的代码,因此加速增益为227。

加速卡尔曼滤波的使用dspunfold

使用生成一个多线程MEX文件dspunfold并将其性能与codegen

Sig = dsp。SineWave (“SamplesPerFrame”, 4000,“SampleRate”, 19200);%创建信号源R = 0.02;%测量噪声协方差trueVal =步骤(Sig);%实际值noisyVal = trueVal + sqrt(R)*randn;噪声测量dspunfoldkalmanfilterarg游戏{noisyVal}- s汽车
状态长度:[autodetect]帧,重复:1,输出延迟:8帧,线程:4分析:kalmanfilter。m创建单线程MEX文件:kalmanfilter_st。搜索最小状态长度(这可能需要一些时间)检查无状态…不足检查1帧…创建多线程MEX文件:kalmanfilter_mt。正在创建分析文件:kalmanfilter_analyzer.p

调用analyzer函数。

kalmanfilter_analyzer ([noisyVal; 0.01 * noisyVal; 0.05 * noisyVal; 0.1 * noisyVal]);
分析多线程MEX文件kalmanfilter_mt.mexw64。为了达到最佳效果,请避免与计算机交互,并在分析仪完成之前停止其他进程。延迟= 8帧加速= 0.7x

kalmanfilter_mt是否有加速因子0.7,即性能损失为30%与单线程MEX文件相比,kalmanfilter_st.将重复因子增加到3.看看性能是否会提高。同时,检测样品中的状态长度。

dspunfoldkalmanfilterarg游戏{noisyVal}- s汽车- f真正的- r3.
状态长度:[自动检测]样本,重复:3,输出延迟:24帧,线程:4分析:kalmanfilter。m创建单线程MEX文件:kalmanfilter_st。搜索最小状态长度(这可能需要一些时间)检查无状态…检查4000个样品…检验2000个样品…检验1000个样品…检验500个样品…检验250个样品…检查375个样品…312个样品…281个样品… Sufficient Checking 265 samples ... Sufficient Checking 257 samples ... Insufficient Checking 261 samples ... Sufficient Checking 259 samples ... Sufficient Checking 258 samples ... Insufficient Minimal state length is 259 samples Creating multi-threaded MEX file: kalmanfilter_mt.mexw64 Creating analyzer file: kalmanfilter_analyzer.p

调用analyzer函数。

kalmanfilter_analyzer ([noisyVal; 0.01 * noisyVal; 0.05 * noisyVal; 0.1 * noisyVal]);
分析多线程MEX文件kalmanfilter_mt.mexw64。为了达到最佳效果,请避免与计算机交互,并在分析仪完成之前停止其他进程。延迟= 24帧加速= 1.4倍

dspunfold给出一个加速增益40%与高度优化的单线程MEX文件相比。指定确切的状态长度,并将重复因子增加到4

dspunfoldkalmanfilterarg游戏{noisyVal}- s259- f真正的- r4
状态长度:259个样本,重复:4,输出延迟:32帧,线程:4分析:kalmanfilter。m创建单线程MEX文件:kalmanfilter_st。mexw64创建多线程MEX文件:kalmanfilter_mt。正在创建分析文件:kalmanfilter_analyzer.p

调用分析器函数查看加速增益。

kalmanfilter_analyzer ([noisyVal; 0.01 * noisyVal; 0.05 * noisyVal; 0.1 * noisyVal]);
分析多线程MEX文件kalmanfilter_mt.mexw64。为了达到最佳效果,请避免与计算机交互,并在分析仪完成之前停止其他进程。延迟= 32帧加速= 1.5倍

加速增益因子为50%与单线程MEX文件相比。

性能增益因素codegen而且dspunfold取决于你的算法。codegen为一些MATLAB结构提供了足够的加速度。dspunfold可以使用计算机上可用的核心通过展开分发算法来提供额外的性能增益。如本例所示,加速量为dspunfold提供的加速取决于特定的算法。使用dspunfold除了codegen如果你的算法非常适合通过展开进行分配,并且产生的延迟成本符合应用程序的约束条件。

一些MATLAB结构是高度优化的MATLAB解释执行。的fft例如,函数在解释模拟中比在代码生成中运行得快得多。

相关的话题