仿真加速使用MATLAB编码器和并行计算工具箱
本例展示了在MATLAB®中加速通信算法仿真的两种方法。它展示了使用MATLAB对C代码生成和并行处理运行的运行时性能影响(使用MATLABparfor
(并行计算工具箱)功能)。要全面了解所有可能的加速技术,请参见加速MATLAB算法及应用篇文章。
使用这些方法的综合效果可以使典型的模拟时间加快一个数量级。这种差异相当于在一夜之间或短短几个小时内运行模拟。
要运行此示例的MATLAB到C代码生成部分,您必须拥有MATLAB Coder™产品。要运行此示例的并行处理部分,必须使用并行计算工具箱™产品。
示例结构
本例研究了该收发器系统在MATLAB中的各种实现。
该系统由发射机、信道模型和接收机组成。发射器使用卷积编码器、交织器、调制器和MIMO时空块编码器处理输入比特流(参见[1]、[2])。传输信号经过2 × 2 MIMO块衰落信道和加性高斯白噪声信道处理。接收机使用一个2x2 MIMO空时块解码器、一个解调器、一个去交织器和一个维特比解码器处理输入信号,以恢复接收机处输入比特流的最佳估计。
示例如下:
创建一个运行模拟算法的函数
使用MATLAB Profiler GUI识别速度瓶颈
加速仿真用MATLAB到C代码的生成
使用并行处理运行实现更快的模拟
创建运行模拟算法的函数
从表示该算法的第一个版本或基线实现的函数开始。的输入helperAccelBaseline
函数是
当前帧(EbNo
),最小错误数(minNumErr
)和处理的最大比特数(maxNumBits
).
是每比特能量与噪声功率谱密度的比值。函数输出是每个函数的误码率(BER)信息
点。
类型helperAccelBaseline
function ber = helperAccelBaseline(EbNo, minNumErr, maxNumBits) %helperAccelBaseline模拟通信链路% ber = helperAccelBaseline(EbNo, MINERR,MAXBIT)返回通信链路的误码率(ber),该通信链路包括卷积编码,%交织,QAM调制,Alamouti空时块码和% MIMO块衰减信道。EBNO是AWGN信道的每比特能量与%噪声功率谱密度之比(Eb/No),单位为dB, % miner是要收集的最小错误数,MAXBIT是最大模拟比特数%,这样当Eb/No值过高时,模拟不会无限期地运行%。版权所有:The MathWorks, Inc.M = 16;%调制阶k = log2(M);%比特每符号codeRate = 1/2;%编码率adjSNR = convertSNR(EbNo," EbNo ","BitsPerSymbol",k,"CodingRate",codeRate);格子= poly2trellis(7,[171 133]);Tblen = 32;dataFrameLen = 1998; % Add 6 zeros to terminate the convolutional code chanFrameLen=(dataFrameLen+6)/codeRate; permvec=[1:3:chanFrameLen 2:3:chanFrameLen 3:3:chanFrameLen]'; ostbcEnc = comm.OSTBCEncoder(NumTransmitAntennas=2); ostbcComb = comm.OSTBCCombiner(NumTransmitAntennas=2,NumReceiveAntennas=2); mimoChan = comm.MIMOChannel(MaximumDopplerShift=0,PathGainsOutputPort=true); berCalc = comm.ErrorRate; % Run Simulation ber = zeros(3,1); while (ber(3) <= maxNumBits) && (ber(2) < minNumErr) data = [randi([0 1],dataFrameLen,1);false(6,1)]; encOut = convenc(data,trellis); % Convolutional Encoder intOut = intrlv(double(encOut),permvec'); % Interleaver modOut = qammod(intOut,M,... 'InputType','bit'); % QAM Modulator stbcOut = ostbcEnc(modOut); % Alamouti Space-Time Block Encoder [chanOut, pathGains] = mimoChan(stbcOut); % 2x2 MIMO Channel chEst = squeeze(sum(pathGains,2)); rcvd = awgn(chanOut,adjSNR,'measured'); % AWGN channel stbcDec = ostbcComb(rcvd,chEst); % Alamouti Space-Time Block Decoder demodOut = qamdemod(stbcDec,M,... 'OutputType','bit'); % QAM Demodulator deintOut = deintrlv(demodOut,permvec'); % Deinterleaver decOut = vitdec(deintOut(:),trellis, ... % Viterbi Decoder tblen,'term','hard'); ber = berCalc(decOut(1:dataFrameLen),data(1:dataFrameLen)); end
作为起点,测量在MATLAB中运行此基线算法所需的时间。使用MATLAB定时函数(抽搐
而且toc
)来记录经过的运行时,以完成for循环的遍历处理
值从0到7 dB。
minEbNodB = 0;maxEbNodB = 7;EbNoVec = minEbNodB:maxEbNodB;minNumErr = 100;maxNumBits = 1 e6;N = 1;str =“基线”;运行该函数一次,将其加载到内存中,并从内存中删除开销%运行时测量1 e4 helperAccelBaseline(10日);berBaseline = 0(大小(minEbNodB: maxEbNodB));disp ('处理基线算法。');
处理基线算法。
抽搐;为EbNoIdx=1:length(EbNoVec) EbNo = EbNoVec(EbNoIdx);y = helperAccelBaseline (EbNo minNumErr maxNumBits);berBaseline (EbNoIdx) = y (1);结束rtBaseline = toc;
结果显示了基线算法的仿真时间(单位为秒)。使用此计时测量与后续加速模拟运行时进行比较。
helperAccelReportResults (N, rtBaseline rtBaseline str, str);
---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 5.5712 | 1.0000 ----------------------------------------------------------------------------------------------
通过使用MATLAB Profiler App识别速度瓶颈
使用MATLAB Profiler识别基线算法的处理瓶颈和问题领域。通过执行以下脚本获取分析器信息:
配置文件在y = helperAccelBaseline(6100年,1 e6);配置文件从配置文件查看器
的性能分析报告显示算法的每个函数调用的执行时间。您可以根据函数的自时间降序对它们进行排序。Profiler窗口描述的前几个函数表示算法的速度瓶颈。在这种情况下,vitdec
功能被认为是主要的速度瓶颈。
用MATLAB加速仿真生成C代码
MATLAB Coder从属于MATLAB代码生成子集的算法生成可移植和可读的C代码。可以创建一个MATLAB可执行文件(MEX)的helperAccelBaseline
,因为它使用了支持代码生成的函数和系统对象。金宝app使用codegen
(MATLAB编码器)函数编译helperAccelBaseline
函数转换为MEX函数。在codegen成功生成代码后,您将在工作区中看到一个MEX文件,该文件将'_mex'附加到函数中,helperAccelBaseline_mex
.
codegen (“helperAccelBaseline.m”,“参数”, {EbNo、minNumErr maxNumBits})
代码生成成功。
测量MEX版本算法的仿真时间。记录在相同的for循环中运行此函数所花费的时间。
N = N + 1;str =MATLAB到C代码生成;标签=“Codegen”;1 e4 helperAccelBaseline_mex(10日);berCodegen = 0(大小(berBaseline));disp (处理算法的MEX函数);
处理算法的MEX函数。
抽搐;为EbNoIdx=1:length(EbNoVec) EbNo = EbNoVec(EbNoIdx);y = helperAccelBaseline_mex (EbNo minNumErr maxNumBits);berCodegen (EbNoIdx) = y (1);结束rt = toc;
这里的结果表明,该算法的MEX版本比算法的基线版本运行得更快。实现的加速量取决于算法的性质。确定加速度的最佳方法是使用MATLAB Coder生成一个mex函数并直接测试加速。如果您的算法包含单精度数据类型、定点数据类型、带状态的循环或不能向量化的代码,则可能会看到加速。另一方面,如果您的算法包含MATLAB的隐式多线程计算,如fft
而且圣言会
例如,调用IPP或BLAS库的函数,为在PC上的MATLAB中执行而优化的函数(如fft),或者可以向量化代码的算法,这些都不太可能加速。
helperAccelReportResults (N, rtBaseline, rt、str标记);
---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 5.5712 | 1.0000MATLAB与C代码生成| 1.6952 | 3.2864 ----------------------------------------------------------------------------------------------
使用并行处理运行实现更快的模拟
利用多核通过并行运行任务来增加模拟加速。使用并行处理运行(parfor
循环)在MATLAB中执行的工作上可用的工人的数量。“并行计算工具箱”使您能够并行地运行模拟的不同迭代。使用gcp
(并行计算工具箱)函数获取当前并行池。如果池可用但未打开,则gcp
打开池并保留几个MATLAB工作者来执行后续的迭代parfor
循环。在本例中,有6个worker在MATLAB客户机上本地运行。
Pool = GCP
使用“本地”配置文件启动并行池(parpool)…连接到并行池(number of workers: 6). pool = ProcessPool with properties: Connected: true NumWorkers: 6 Busy: false Cluster: local AttachedFiles: {} AutoAddClientPath: true IdleTimeout: 30 minutes(剩余30分钟)SpmdEnabled: true
并行运行Eb/No值
运行
点平行使用六个工人使用一个parfor
-loop而不是前面使用的for循环。测量模拟时间。
N = N + 1;str =“平行运行与parfor在Eb/No”;标签=“Parfor Eb /不”;1 e4 helperAccelBaseline_mex(10日);berParfor1 = 0(大小(berBaseline));disp (在parfor循环中处理算法的MEX函数);
在parfor-loop中处理算法的MEX函数。
抽搐;parforEbNoIdx=1:length(EbNoVec) EbNo = EbNoVec(EbNoIdx);y = helperAccelBaseline_mex (EbNo minNumErr maxNumBits);berParfor1 (EbNoIdx) = y (1);结束rt = toc;
结果添加了算法的MEX版本的仿真时间parfor
-循环到之前的结果。注意,通过在parfor
-loop,完成模拟所需的时间更短。a的基本概念parfor
-loop与标准的MATLAB for-loop相同。区别在于parfor
将循环迭代划分为组,以便每个工作人员执行迭代总数的一部分。因为几个MATLAB工作者可以在同一个循环上并发地计算,aparfor
-loop提供了比普通串行for循环更好的性能。
helperAccelReportResults (N, rtBaseline, rt、str标记);
---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 5.5712 | 1.0000用MATLAB编写的C代码生成| 1.6952 | 3.2864 3.。并行运行与parfor Eb /不| 1.4367 | 3.8779 ----------------------------------------------------------------------------------------------
并行运行比特数
在上一节中,总的模拟时间主要由最高来决定
点。您可以通过划分每个模拟的比特数来进一步加速模拟
指向工人们。运行每个
点平行使用六个工人使用一个parfor
循环。测量模拟时间。
N = N + 1;str =并行运行parfor超过比特数;标签=Parfor # Bits;1 e4 helperAccelBaseline_mex(10日);berParfor2 = 0(大小(berBaseline));disp (在parfor-loop中处理算法的第二个版本的MEX函数);
在parfor-loop中处理算法的第二个版本的MEX函数。
抽搐;计算要在每个worker上模拟的比特数minNumErrPerWorker = minNumErr / pool.NumWorkers;maxNumBitsPerWorker = maxNumBits / pool.NumWorkers;为EbNoIdx=1:length(EbNoVec) EbNo = EbNoVec(EbNoIdx);number r = 0 (pool.NumWorkers,1);parforw = 1:池。NumWorkers y=helperAccelBaseline_mex(EbNo,minNumErrPerWorker,maxNumBitsPerWorker); numErr(w)=y(2); numBits(w)=y(3);结束berParfor2 (EbNoIdx) = (numErr) /金额总和(numBits);结束rt = toc;
结果添加了算法的MEX版本的仿真时间parfor
-loop,这一次每个worker模拟相同的
点。注意,通过在parfor
我们得到了最快的模拟性能。区别在于parfor
将需要模拟的比特数除以worker。这种方法减少了仿真时间,即使是最高的
通过在工人上均匀分配负载(具体来说,要模拟的比特数)来计算值。
helperAccelReportResults (N, rtBaseline, rt、str标记);
---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 5.5712 | 1.0000用MATLAB编写的C代码生成| 1.6952 | 3.2864 3.。b/No | 1.4367 | 3.8779 4。并行运行与parfor | 0.9522 | 5.8507的比特数 ----------------------------------------------------------------------------------------------
总结
通过MATLAB到C代码生成和并行处理运行的组合效果,您可以显著加快通信算法的模拟速度。
MATLAB到C的代码生成通过锁定每个变量的数据类型和大小,以及通过减少解释语言的开销来加速模拟,解释语言在代码的每一行中检查变量的大小和数据类型。
并行处理运行可以通过在多个MATLAB工作线程上并行计算算法的不同迭代来大大加速仿真。
并行每个 点单独可以加速进一步加速,即使是最长的运行 点。
下面以柱状图的形式显示了所有四种方法的运行时间。结果可能会根据特定的算法、可用的worker以及对最小错误数和最大比特数的选择而有所不同。
results = helperAccelReportResults;
该图显示了不同仿真处理方法的误码率曲线彼此紧密匹配。对于每一个绘图
该算法的四个版本中,每个版本的最大输入位数都设置为1000万(maxNumBits
=1e7),最小误码数设置为5000 (minNumErr
= 5000)。
进一步的探索
本例使用gcp
函数保留几个在MATLAB客户端机器上本地运行的MATLAB工作者。通过修改并行配置,可以在不在MATLAB客户端机器上的更大的工作集群上运行算法,从而进一步加速模拟。有关如何管理和使用并行配置的说明,请参见发现集群并使用集群概要文件(并行计算工具箱)的话题。
本例中使用了以下函数。
选择引用
S. M. Alamouti,“一种简单的无线通信传输分集技术”IEEE通信选定领域期刊,第16卷,no。8,页1451-1458,1998年10月。
V. Tarokh, H. Jafarkhami和A. R. Calderbank,“正交设计中的时空分组码”,IEEE信息论汇刊,第45卷,no。5,第1456-1467页,1999年7月。