主要内容

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

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

此示例特性的系统对象可在“通信工具箱”产品中访问。要运行此示例,您必须拥有MATLAB Coder许可证、并行计算工具箱许可证和足够的GPU。

系统设计与仿真参数

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

  • convolutionalencoder -卷积编码

  • pskmodulator - QPSK调制

  • com . awgnchannel - AWGN通道

  • psk解调器- QPSK解调(近似LLR)

  • viterbidecoder -维特比解码

收发器的代码可以在以下地址找到:

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

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

初始化

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

Errs = 0(长度(snrdb),1);= 0(长度(snrdb),1);Berplot = cell(1,5);Numframes = 500;%GPU版本并行运行500帧。viterbiTransceiverCPU(-10年,1,1);viterbiTransceiverGPU(-10、1、1、numframes);N = 1;%N跟踪正在运行的模拟变量

工作流

这个例子的工作流程是:

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

  2. 使用MATLAB Coder生成MEX函数进行仿真

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

  4. 将生成的MEX函数与parfor结合起来

  5. 使用基于gpu的System对象

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

基线模拟

为建立各种加速策略的参考点,仅使用系统对象生成误码率曲线。收发器的代码已经输入了viterbiTransceiverCPU.m

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

代码生成

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

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

流(1,'\n***基线+代码原***\n');N = N + 1;增加模拟计数器创建编码器对象并关闭将导致低的检查%的性能。流(1,“生成代码……”);Config_obj = code .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}) fprintf(1,“。\ n”);%运行一次以消除启动开销。viterbiTransceiverCPU_mex(-10年,1,1);s = RandStream.getGlobalStream;重置(年代);使用生成的MEX函数viterbiTransceiverCPU_mex%模拟循环。Ts = tic;2 = 1:元素个数(snrdb)流(1,'迭代数%d,信噪比(dB) = %d\n'第二,snrdb (ii));[errs(ii), (ii)] = viterbiTransceiverCPU_mex(snrdb(ii), minErrThreshold, iterCntThreshold);结束误码。/ (msgL*);trialtime = toc (ts);berplot{N} = ber;desc {N} =“codegen”;reportResultsCommSysGPU (N trialtime baseTime“基线+编码原”);
***基线+代码生成***生成代码…代码生成成功。完成了。迭代1号,信噪比(dB) = 1迭代2号,信噪比(dB) = 2迭代3号,信噪比(dB) = 3迭代4号,信噪比(dB) = 4迭代5号,信噪比(dB) = 5  ---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 17.0205 | 1.0000基线+ codegen | 14.3820 | 1.1835  ----------------------------------------------------------------------------------------------

Parfor -并行循环执行

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

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

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

Parfor和代码生成

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

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

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

GPU

的系统对象viterbiTransceiverCPU函数使用可以在GPU上执行。基于gpu的版本有:

  • convolutionalencoder -卷积编码

  • pskmodulator - QPSK调制

  • com .gpu. awgnchannel - AWGN通道

  • psk解调器- QPSK解调(近似LLR)

  • viterbidecoder -维特比解码

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

您必须拥有并行计算工具箱许可证和支持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 = tic;2 = 1:元素个数(snrdb)流(1,'迭代数%d,信噪比(dB) = %d\n'第二,snrdb (ii));[errs(ii), (ii)] =viterbiTransceiverGPU(snrdb(ii), minErrThreshold, iterCntThreshold, numframes);结束误码。/ (msgL*);trialtime = toc (ts);berplot{N} = ber;desc {N} =“图形”;reportResultsCommSysGPU (N trialtime baseTime“基线+ GPU”);流(1,“。\ n”);% #好< CTCH >%报告没有找到合适的GPU。流(1,“找不到合适的GPU”...\n']);结束
* * * * * * GPU GPU检测(特斯拉V100-PCIE-32GB 80多处理器计算能力7.0)迭代1号,信噪比(dB) = 1迭代2号,信噪比(dB) = 2迭代3号,信噪比(dB) = 3迭代4号,信噪比(dB) = 4迭代5号,信噪比(dB) = 5  ---------------------------------------------------------------------------------------------- 版本的收发机|运行时间(sec) |加速度比1。基线| 17.0205 | 1.0000基线+密码| 14.3820 | 1.18354.基线+ parfor | 2.6984 | 6.3075基线+编码原+ parfor | 2.7059 | 6.2902基线+ GPU | 0.1895 | 89.8137  ---------------------------------------------------------------------------------------------- 完成了。

分析

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

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

清理

保持平行池状态不变。

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