问题:
小明是作为通信专业的新生,目前还是通信领域的一名小白。他利用课余时间自学了无线通信的一点基础知识,了解到了误码率这个概念。为了加深理解,小明写了一段 MATLAB 程序进行仿真。然而,他发现程序运行起来很慢,尤其是当参数MaxSNR的值较大的时候(试一试将 MaxSNR 的改成 11, 12 或者更大并运行程序)。看着 Windows任务管理器中被占满的 CPU 时间,听着电脑风扇无止尽地咆哮,小明一筹莫展。
任务:
请你读懂 MATLAB 程序,尤其是 error_cal 函数的代码,分析其运行的时间消耗。然后运用混合编程技术,将 error_cal 函数改用 C/C++语言编写,调节参数进行实验,分析比较两种语言的运行效率。
原matlab代码如下: main.m
%-------------------------------------------------------------------------%
% 主函数
% (1)这段代码中涉及到无线通信的一些概念,你不需要弄懂这些代码的物理意义,只
% 需要从纯代码的角度完成MATLAB程序到C/C++程序的转换,就可以完成这次作业。
% (2)有兴趣了解这些概念的,请阅读题目后的Hints,并查阅相关资料。
%-------------------------------------------------------------------------%
clear;
MaxSNR = 10;
SampleNum = 1e6;
MinErrorNum = 100;
SNRrange = 0:MaxSNR;
tic
index = 1;
for SNR = SNRrange
P = 10^(SNR/10);
error_prob_theory(index) = 1/2*erfc(sqrt(P));
total_error = 0;
total_sample = 0;
while (total_sample < SampleNum | total_error < MinErrorNum)
[d, noise] = data_generate(SampleNum);
error_num = error_cal(P, d, noise, SampleNum);
total_sample = total_sample + SampleNum;
total_error = total_error + error_num;
end
error_prob_sim(index) = total_error/total_sample;
index = index + 1;
end
toc
figure; semilogy(SNRrange, error_prob_theory, '-or', SNRrange, error_prob_sim, '-*b', 'LineWidth', 2, 'markersize', 8);
xlabel('SNR');
ylabel('Bit Error Probability');
legend('Theory', 'Simulation');
set(get(gca,'XLabel'),'FontSize',16);
set(get(gca,'YLabel'),'FontSize',16);
set(gca,'fontsize',14);
grid on;
data_generate.m
function [d noise] = data_generate(SampleNum)
d = round(rand(1, SampleNum));
noise = randn(1, SampleNum)/sqrt(2);
error_cal.m
function error_num = error_cal(P, d, noise, SampleNum)
error_num = 0;
for i = 1:SampleNum
x = sqrt(P)*(2*d(i)-1);
y = x + noise(i);
r = (y > 0);
error_num = error_num + (r ~= d(i));
end
本人使用的是codeblocks、matalbR2017a,同时安装了tdm64-gcc-5.1.0-2。
需要注意的是,matlab的版本不能过低,否则原代码运行会十分缓慢。
先来研究如何修改原matlab代码。
对error_cal.m文件的内容进行分析,把matlab代码改成c语言形式,并研究如何建立matlab与c的接口。
最终版本如下,保存在error_cal.cpp文件里。
#include "mex.h"
#include "stdio.h"
#include <math.h>
int error_cal(double p,double d[],double noise[],double large){
int error_num=0;
double x=0,y=0,r=0;
int i=0;
for(i=0;i<large;i++)
{
x=pow(p,0.5)*(2*d[i]-1);
y=x+noise[i];
r=(y>0);
error_num+=(r!=d[i]);
}
return error_num;
}
void mexFunction(int nlhs, mxArray *plhs[] ,int nrhs,const mxArray * prhs[])
{
double p = mxGetScalar(prhs[0]);
double *d = mxGetPr(prhs[1]);
double *noise = mxGetPr(prhs[2]);
double large = mxGetScalar(prhs[3]);
int result=error_cal(p,d,noise,large);
plhs[0] = mxCreateDoubleScalar(result);
}
以上代码最重要的部分即为: Matalb与c使用 void mexFunction(int nlhs, mxArray *plhs[] ,int nrhs,const mxArray * prhs[]) 函数接口。
使用 mxGetScalar( )、mxGetPr( ) 读取输入值。
使用 mxCreateDoubleScalar( ) 写入输出值。
同时,在main.m中,调用该函数的语句需要修改为:
%在main.m中调用该函数的语句:
error_num = error_cal(P, d, noise, SampleNum);
那么下面的问题是,我们如何在matlab中使用这个 .cpp 文件呢?
我们需要做的,首先是建立 matlab与c 的接口。
在电脑上添加环境变量。
有两种方法。 方法一:
在matalb命令行窗口输入如下代码:
setenv('MW_MINGW64_LOC','C:\TDM-GCC-64');
方法二:
此电脑右键——属性——高级——环境变量——新建用户变量,输入内容如下图所示:
在matlab的命令行窗口输入代码
mex -setup
输入以后显示的界面如下:
选择mex -setup C++
输入代码
mex error_cal.cpp
这时候检查一下存放 error_cal.cpp 的文件夹,如果以上均成功的话会出现一个 .mexw64 文件。
就可以使用了。
经过对比两种编译方式运行所需要的时间,matlab c/c++混合编程的确可以提高运行速度。
|
请发表评论