主要内容

使用gpu的端到端系统仿真加速

这个例子展示了在MATLAB®Communications Toolbox™软件中使用系统对象来加速误码率(BER)模拟的四种技术的比较。一个基于卷积编码的小系统,说明了使用MATLAB®Coder™产品生成代码的效果,使用并行循环执行parfor在并行计算工具箱™产品中,代码生成和parfor、基于gpu的System对象。

在“通信工具箱”产品中可以访问此示例特性的System对象。为了运行这个例子,你必须有一个MATLAB编码器许可证,一个并行计算工具箱许可证,和一个足够的GPU。

系统设计与仿真参数

这个例子使用一个简单的卷积编码系统来说明仿真加速策略。系统产生随机信息位使用兰迪.发射机使用速率为1/2的卷积编码器对这些比特进行编码,应用QPSK调制方案,然后传输这些符号。这些符号通过一个AWGN通道,信号损坏在这里发生。QPSK解调发生在接收机,并使用维特比算法解码损坏的比特。最后计算了误码率。系统中使用的System对象有:

  • comm.ConvolutionalEncoder—卷积编码

  • comm.PSKModulator—QPSK调制

  • comm.AWGNChannel—AWGN频道

  • 通信psk解调器- QPSK解调(约LLR)

  • com . viterbidecoder -维特比解码

无线电收发机的代码可以在以下目录中找到:

比特误码率曲线上的每一点都代表了上述收发码多次迭代的结果。为了在合理的时间内获得准确的结果,仿真将收集每个信噪比(SNR)值至少200个比特的错误,最多5000个数据包的数据。一个包代表2000个消息位。信噪比的取值范围为1db ~ 5db。

iterCntThreshold = 5000;minErrThreshold = 200;msgL = 2000;snrdb = 1:5;

初始化

调用一次收发器函数以推算出设置时间和对象构造开销。对象存储在每个函数的持久变量中。

犯错误= 0(长度(snrdb), 1);iter = 0(长度(snrdb), 1);berplot =细胞(1、5);numframes = 500;%GPU版本并行运行500帧。viterbiTransceiverCPU(-10年,1,1);viterbiTransceiverGPU(-10、1、1、numframes);N = 1;%N跟踪哪个模拟变量正在运行

工作流

这个例子的工作流程是:

  1. 运行一个系统对象的基线模拟

  2. 使用MATLAB编码器生成一个MEX函数进行仿真

  3. 使用parfor并行运行误码率模拟

  4. 将生成的MEX函数与parfor结合使用

  5. 使用基于gpu的System对象

流(1,“误码率加速分析示例\n\n”);
误码率加速分析示例

基线模拟

为建立各种加速度策略的参考点,仅使用System对象生成误码率曲线。无线电收发机的密码已经输入了viterbiTransceiverCPU.m

流(1,***基线-标准系统对象模拟***\n');%为每个SNRDB模拟创建随机流s = RandStream.create (“mrg32k3a”“NumStreams”,1,...“CellOutput”,真的,“NormalTransform”“反转”);RandStream.setGlobalStream (s {1});ts =抽搐;2 = 1:元素个数(snrdb)流(1,'迭代数%d,信噪比(dB) = %d\n'第二,snrdb (ii));[errs(ii),iter (ii)] = viterbitranscivercpu (snrdb(ii), minErrThreshold, iterCntThreshold);结束数量=犯错误。/ (msgL * iter);baseTime = toc (ts);berplot {N} = 1;desc {N} =“基线”;reportResultsCommSysGPU (N baseTime baseTime“基线”);
***基准-标准系统对象仿真***迭代数1,SNR (dB) = 1迭代数2,SNR (dB) = 2迭代数3,SNR (dB) = 3迭代数4,SNR (dB) = 4迭代数5,SNR (dB) = 4信噪比(dB) = 5  ---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 17.0205 | 1.0000  ----------------------------------------------------------------------------------------------

代码生成

使用MATLAB Coder,可以用与预编译的MATLAB代码匹配的优化C代码生成MEX文件。因为viterbiTransceiverCPU函数符合MATLAB代码生成子集,可以编译成MEX函数而无需修改。

您必须有MATLAB Coder许可证才能运行示例的这一部分。

流(1,' \ n * * *基线+ codegen * * * \ n”);N = N + 1;%增加模拟计数器%创建编码器对象并关闭会导致低电平的检查%的性能。流(1,“生成代码…”);config_obj = coder.config (墨西哥人的);config_obj。EnableDebugging = false;config_obj。IntegrityChecks = false;config_obj。ResponsivenessChecks = false;config_obj。EchoExpressions = false;%生成MEX文件codegen (“viterbiTransceiverCPU.m”“配置”“config_obj”“参数”, {snrdb(1), minErrThreshold, iterCntThreshold})“。\ n”);%运行一次以减少启动开销。viterbiTransceiverCPU_mex(-10年,1,1);s = RandStream.getGlobalStream;重置(年代);%使用生成的MEX函数viterbitranscivercpu_mex%模拟循环。ts =抽搐;2 = 1:元素个数(snrdb)流(1,'迭代数%d,信噪比(dB) = %d\n'第二,snrdb (ii));[errs(ii),iter (ii)] = viterbiTransceiverCPU_mex(snrdb(ii), minErrThreshold, iterCntThreshold);结束数量=犯错误。/ (msgL * iter);trialtime = toc (ts);berplot {N} = 1;desc {N} =“codegen”;reportResultsCommSysGPU (N trialtime baseTime“基数+ codegen”);
***基线+ codegen***生成代码…代码生成成功。完成了。迭代1号,信噪比(dB) = 1迭代2号,信噪比(dB) = 2迭代3号,信噪比(dB) = 3迭代4号,信噪比(dB) = 4迭代5号,信噪比(dB) = 5  ---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 17.0205 | 1.0000 2。基线+ codegen | 14.3820 | 1.1835  ----------------------------------------------------------------------------------------------

Parfor—并行循环执行

使用parfor, MATLAB对所有信噪比值并行执行收发码。这需要打开并行池并添加parfor循环。

您必须拥有并行计算工具箱许可证才能运行示例的这一部分。

流(1,' \ n * * *基线+ parfor * * * \ n”);流(1,“访问多个CPU内核……\n”);如果isempty (gcp (“nocreate”pool =游泳池;poolWasOpen = false;其他的池=质量;poolWasOpen = true;结束西北= pool.NumWorkers;N = N + 1;%增加模拟计数器snrN =元素个数(snrdb);mT = minErrThreshold / nW;iT = iterCntThreshold / nW;errN = 0 (nW, snrN);itrN = zero (nW, snrN);%复制snrdbsnrdb_rep = repmat (snrdb, nW, 1);为每个worker创建一个独立的流s = RandStream.create (“mrg32k3a”“NumStreams”西北,...“CellOutput”,真的,“NormalTransform”“反转”);%跑前parforjj = 1:西北RandStream.setGlobalStream (s {jj});viterbiTransceiverCPU(-10年,1,1);结束流(1,“开始parfor工作……”);ts =抽搐;parforjj = 1:西北ii=1:snrN [err, itr] = viterbiTransceiverCPU(snrdb_rep(jj,ii), mT, iT);errN (jj, ii) =犯错;itrN (jj, ii) = itr;结束结束数量= (errN)之和。/ (msgL *总和(itrN));trialtime = toc (ts);流(1,“。\ n”);berplot {N} = 1;desc {N} =“parfor”;reportResultsCommSysGPU (N trialtime baseTime“基数+ parfor”);
***Baseline + parfor***访问多个CPU核…使用“local”配置文件启动并行池(parpool)…连接到并行池(worker数量:8)。完成了。---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 17.0205 | 1.0000 2。基线+ codegen | 14.3820 | 1.1835 3。基线+ parfor | 2.6984 | 6.3075  ----------------------------------------------------------------------------------------------

Parfor和代码生成

您可以结合使用最后两种技术来获得额外的加速。编译后的MEX函数可以在parfor循环。

您必须拥有MATLAB编码器许可证和并行计算工具箱许可证才能运行示例的这一部分。

流(1,'\n***Baseline + codegen + parfor***\n');N = N + 1;%增加模拟计数器%跑前parforjj = 1:西北RandStream.setGlobalStream (s {jj});viterbiTransceiverCPU_mex (1 1 1);%使用相同的mex文件结束流(1,“开始parfor工作……”);ts =抽搐;parforjj = 1:西北ii=1:snrN [err, itr] = viterbiTransceiverCPU_mex(snrdb_rep(jj,ii), mT, iT);errN (jj, ii) =犯错;itrN (jj, ii) = itr;结束结束数量= (errN)之和。/ (msgL *总和(itrN));trialtime = toc (ts);流(1,“。\ n”);berplot {N} = 1;desc {N} =“codegen + parfor”;reportResultsCommSysGPU (N trialtime baseTime“基线+ codegen + parfor”);
***Baseline + codegen + parfor*** Start parfor job…完成了。---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 17.0205 | 1.0000 2。基线+ codegen | 14.3820 | 1.1835 3。基线+ parfor | 2.6984 | 6.3075 4。基线+ codegen + parfor | 2.7059 | 6.2902  ----------------------------------------------------------------------------------------------

GPU

系统对象viterbiTransceiverCPU功能使用可在GPU上执行。基于gpu的版本包括:

  • convolutionalencoder—卷积编码

  • pskmodulator—QPSK调制

  • com .gpu. awgnchannel—AWGN通道

  • - QPSK解调(约LLR)

  • com .gpu. viterbidecoder - Viterbi解码

GPU在一次处理大量数据时效率最高。基于gpu的System对象可以在对step方法的单个调用中处理多个帧。的numframes变量表示每次调用处理的帧数。这类似于parfor除了并行度是基于每个对象,而不是perviterbiTransceiverCPU调用基础。

你必须有一个并行计算工具箱许可证和一个CUDA®1.3的GPU来运行这个部分的例子。

流(1,' \ n * * * * * * GPU \ n”);N = N + 1;%增加模拟计数器试一试dev = parallel.gpu.GPUDevice.current;流(...'检测到GPU (%s, %d多处理器,计算能力%s)\n'...dev.Name、dev.MultiprocessorCount dev.ComputeCapability);sg = parallel.gpu.RandStream.create (“mrg32k3a”“NumStreams”,1,“NormalTransform”“反转”);parallel.gpu.RandStream.setGlobalStream (sg);ts =抽搐;2 = 1:元素个数(snrdb)流(1,'迭代数%d,信噪比(dB) = %d\n'第二,snrdb (ii));[errs(ii),iter (ii)] = viterbitranssceivergpu (snrdb(ii), minErrThreshold, iterCntThreshold, numframes);结束数量=犯错误。/ (msgL * iter);trialtime = toc (ts);berplot {N} = 1;desc {N} =“图形”;reportResultsCommSysGPU (N trialtime baseTime“基数+ GPU”);流(1,“。\ n”);% #好< CTCH >%报告没有找到合适的GPU。流(1,“找不到合适的GPU或无法”...“GPU执行代码。\ n”]);结束
***GPU***检测到的GPU (Tesla 100- pcie - 32gb, 80多处理器,计算能力7.0)迭代数1,SNR (dB) = 1迭代数2,SNR (dB) = 2迭代数3,SNR (dB) = 3迭代数4,SNR (dB) = 4迭代数5,信噪比(dB) = 5  ---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 17.0205 | 1.0000 2。基线+ codegen | 14.3820 | 1.1835 3。基线+ parfor | 2.6984 | 6.3075 4。基线+ codegen + parfor | 2.7059 | 6.2902 5。基线+ GPU | 0.1895 | 89.8137  ---------------------------------------------------------------------------------------------- 完成了。

分析

比较这些试验的结果,很明显,GPU比任何其他模拟加速技术都要快得多。这种性能提升需要对模拟代码进行非常温和的更改。然而,比特误码率性能没有损失,如下图所示。曲线上的微小差异是由于不同的随机数生成算法和/或对曲线上同一点的不同数量的数据进行平均的影响。

行= {“kx -。”“ro - - - - - -”“cs——”“m ^:”“g * - - - - - -”};Ii =1:numel(desc) semilogy(snrdb, berplot{Ii}, lines{Ii});持有结束持有;标题(“各种加速策略的误码率”);包含(“信噪比(dB)”);ylabel (“方方面面”);传奇(desc {:});

清理

让并行池保持原来的状态。

如果~ poolWasOpen删除(gcp);结束
使用“本地”配置文件的并行池正在关闭。