MATLAB是一个很好用的工具。利用MATLAB脚本进行科学计算也特别方便快捷。但是代码存在较多循环时,MATLAB运行速度极慢。如果不想放弃MATLAB中大量方便使用的库,又希望代码能迅速快捷的运行,可以考虑将循环较多的功能采用C编写,MATLAB调用。本文将概述这一过程。虽然本文以LDPC译码算法为例,但不懂该算法不影响本文阅读。

1. 起因

最开始用MATLAB写的LDPC译码算法中,其中一个版本是这里,里面有三重循环,运行速度极慢。后来考虑了MATLAB的向量化操作,通过算法的合理划分以及内置函数调用,成功将三重循环修改为1层,具体这一版本的代码可见这里。通过这一手段,函数的运行速度提高了几倍乃至几十倍。虽然这一方法下运行速度依旧比不过MATLAB工具箱中的comm.LDPCDecoder,远比不上利用GPU的comm.gpu.LDPCDecoder,但胜在可明确算法并具有一定扩展性。

起初也注意到可以通过MATLAB调用C程序来加速程序运行,但向量化后的代码凑活能用,加上有时也可调用更为强大的内置函数,这一想法一直没有付诸实践。这几天想好好整理一下代码,遂萌发了写一个C版本译码算法的想法。代码现在的状态是“能用”,这里把相关经验总结分析在此。

2. MATLAB调用C程序

这一部分的内容在刘晓辉matlab调用C程序中已经有较为详细的介绍了,想要正确调用C程序,关键概括为2点。

机器上装有MATLAB编译器,可通过在MATLAB命令行窗口输入mex -setup进行具体设置。

有一个正确的接口子程序mexFunction完成MATLAB和C程序之间的数据转换和程序调用

这里给出我写得mexFunction(注意这个代码写得不好,没有任何判断,没有健壮性……)

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
double* llr = (double*)mxGetPr(prhs[]);
int* rownum = mxGetPr(prhs[]);
int* colnum = mxGetPr(prhs[]);
int* trans = mxGetPr(prhs[]);
double* state = mxGetPr(prhs[]);
plhs[] = mxCreateDoubleMatrix(, state[], mxREAL);
double* r =mxGetPr(plhs[]);
ldpcDec( r ,llr, rownum,colnum, trans,state);
}

mexFunction的规范在刘晓辉matlab调用C程序一文中已有提及,即

nlhs:输出参数数目
plhs:指向输出参数的指针

nrhs:输入参数数目

prhs:指向输入参数的指针

例如,在matlab命令行中使用

[a,b]=test(c,d,e)

调用mex函数test时,传给test的这四个参数分别是

2,plhs,3,prhs

其中:

prhs[0]=c

prhs[1]=d

prhs[2]=e

由此可以解释上述mexFunction,而命令plhs[] = mxCreateDoubleMatrix(, state[], mxREAL) 则定义了一大小为1 × state[]的矩阵,做为函数的返回值。最后调用的ldpcDec是一个C程序,运行C程序后plhs[]指向的内存空间存储的就是满足要求的计算结果。ldpcDec代码如下

#include<stdio.h>
#include<math.h>
void ldpcDec(double*r,double* llr, int* rownum, int* colnum, int* trans, double* state){
//列有序,trans为映射关系
//rownum[i]-rownum[i-1],第i+1行的行重
//colnum[i]-colnum[i-1],第i+1列的列重
//state[0]:maxiter state[1]:llr & colnum 长度 state[2] rownum 长度,
//state[3]:H中非零元素个数 state[4]: alpha
double* temp;
double* decodedtemp;
temp = (double*)malloc(sizeof(double)*state[]);
decodedtemp = (double*)malloc(sizeof(double)*state[]);
//init
int ii = ;
for (int i = ; i<state[]; i++){
while (ii<colnum[i]){
temp[ii] = llr[i];
ii++;
}
}
//iter decode
int iter;
for (iter = ; iter<state[]; iter++){
// rowupdate;
for (int i = ; i<state[]; i++){
// temp[] trans[rownum[i-1]]~trans[rownum[i]]
int high = rownum[i];
int low = i> ? rownum[i - ] : ; double minval = fabs(temp[trans[low]]);
double subminval = fabs(temp[trans[low + ]]);
for (int j = low + ; j<high; j++){
if (fabs(temp[trans[j]])<minval){
subminval = minval;
minval = fabs(temp[trans[j]]);
}
else if (fabs(temp[trans[j]])<subminval){
subminval = fabs(temp[trans[j]]);
}
}
int mark = ;
for (int j = low; j < high; j++){
if (temp[trans[j]] < )
mark = -mark;
}
for (int j = low; j<high; j++){
if (fabs(temp[trans[j]]) == minval)
if (temp[trans[j]]<)
temp[trans[j]] = -mark * state[] * subminval;
else
temp[trans[j]] = mark*state[] * subminval;
else
if (temp[trans[j]]<)
temp[trans[j]] = -mark * state[] * minval;
else
temp[trans[j]] = mark*state[] * minval;
}
}
// colupdate;
for (int i = ; i<state[]; i++){
int high = colnum[i];
int low = i> ? colnum[i - ] : ;
double colsum = llr[i];
for (int j = low; j<high; j++){
colsum = colsum + temp[j];
}
if (colsum>)
r[i] = ;
else
r[i] = ;
for (int j = low; j<high; j++){
temp[j] = colsum - temp[j];
decodedtemp[j] = r[i];
}
} // check equation
int errflag = ;
for (int i = ; i<state[]; i++){
int high = rownum[i];
int low = i> ? rownum[i - ] : ;
int sumval = ;
for (int j = low; j<high; j++){
sumval = sumval + decodedtemp[trans[j]];
}
if (sumval % != ){
errflag = ;
break;
}
}
//
if (errflag == )
break;
}
free(temp);/*释放指针pointer*/
temp = NULL;
free(decodedtemp);/*释放指针pointer*/
decodedtemp = NULL;
return;
}

上述代码就是就是一个标准的C函数。

如果程序无误,使用起来是极其方便的。完整的代码如下所示,存储为ldpc_dec.c文件。

在MATLAB命令行窗口输入mex ldpc_dec.c,运行可得到文件ldpc_dec.mexw64(依平台不同可能不同)。需要使用时输入

r = ldpc_dec(receiveSignal,rowNum,colNum,HRowNum,state);

即可。

3. MATLAB调试C程序

一般而言,c程序可以事先调试正确,而mexFunction接口函数较为简单,不容易出错。然而,有时还是出现一些错误,此时可以通过MATLAB对C程序进行调试。以已安装Visual Studio 和 MATLAB的电脑为例,打开MATLAB和Visual Studio。首先准备好需要调试的c代码“ldpc_dec.c”,运行命令“mex ldpc_dec.c -g”表示后续需要对C程序进行调试(参考http://blog.csdn.net/ayw_hehe/article/details/6790147)。

在Visual Studio中点击“调试”-“附加到进程”,选择MATALB,在Visual Studio中打开需要调试的C文件并设置断点,在MATLAB中运行该程序,即输入“ldpc_dec(receiveSignal,rowNum,colNum,HRowNum,state)”后,在设置断点处即会中断。此时进入Visual Studio中,可以进行逐语句的调试,如下图所示

此时,无法操作MATLAB,可以在Visual Studio中进行操作。如果发现自动窗口中的变量取值不正确,调试无法正常进行,那多半是MATLAB数据转化过程中出现了问题,尤其是指针问题。这不仅可能导致运行结果出错,同时可能会倒是MATLAB崩溃。

4. 其他

这是一种比较简单的调用C程序的方法,只需要对已有的C函数进行简单的修改即可。还有其他的方法,譬如调用动态链接库,可以自行查看MATLAB的帮助。

MATLAB调用C程序、调试和LDPC译码的更多相关文章

  1. Matlab调用C程序

    Matlab调用C程序   复制来自https://blog.csdn.net/u010839382/article/details/42463237 Matlab是矩阵语言,如果运算可以用矩阵实现, ...

  2. Matlab调用C程序 分类: Matlab c/c++ 2015-01-06 19:18 464人阅读 评论(0) 收藏

    Matlab是矩阵语言,如果运算可以用矩阵实现,其运算速度非常快.但若运算中涉及到大量循环,Matlab的速度令人难以忍受的.当必须使用for循环且找不到对应的矩阵运算来等效时,可以将耗时长的函数用C ...

  3. matlab 调用C程序进行simulink仿真

    文章目录 simulink仿真 创建C程序 编译C程序 运行结果 simulink仿真 simulink仿真中需要使用S-Function模块,可以实现调用C程序进行仿真,下面先建立一个简单的仿真: ...

  4. matlab调用c程序(转载)

    通过把耗时长的函数用c语言实现,并编译成mex函数可以加快执行速度. Matlab本身是不带c语言的编译器的,所以要求你的机器上已经安装有VC,BC或Watcom C中的一种. 如果你在安装Matla ...

  5. MATLAB 编辑器和程序调试

  6. 【matlab】MATLAB程序调试方法和过程

    3.8  MATLAB程序的调试和优化 在MATLAB的程序调试过程中,不仅要求程序能够满足设计者的设计需求,而且还要求程序调试能够优化程序的性能,这样使得程序调试有时比程序设计更为复杂.MATLAB ...

  7. LDPC译码算法代码概述

    程序说明 V0.0 2015/1/24 LDPC译码算法代码概述   概述   本文介绍了包括LDPC_Simulation.m, ldpcdecoderbp1.m,ldpcdecoderminsum ...

  8. 【系统篇】从int 3探索Windows应用程序调试原理

    探索调试器下断点的原理 在Windows上做开发的程序猿们都知道,x86架构处理器有一条特殊的指令——int 3,也就是机器码0xCC,用于调试所用,当程序执行到int 3的时候会中断到调试器,如果程 ...

  9. .NET应用程序调试—原理、工具、方法

    阅读目录: 1.背景介绍 2.基本原理(Windows调试工具箱..NET调试扩展SOS.DLL.SOSEX.DLL) 2.1.Windows调试工具箱 2.2..NET调试扩展包,SOS.DLL.S ...

随机推荐

  1. ADO.Net(五)——实战:对战游戏

    对战游戏 要求: 自建数据表(例如:数据表包含:代号,姓名,性别,血量,攻击力,防御力,命中,闪避,等级等字段) 需要通过程序向数据表添加人员 添加的时候,根据用户输入的名字,自动计算生成相应的血量. ...

  2. iOS UIButton 图片文字上下垂直布局 解决方案

    实现如图所示效果: 这是一个UIButton,需要改变image和title相对位置. 解决如下: //设置文字偏移:向下偏移图片高度+向左偏移图片宽度 (偏移量是根据[图片]大小来的,这点是关键)b ...

  3. python json

    #-*-coding:utf-8-*- '''编码格式记得统一,不然容易出现中文乱码,推荐用utf-8''' import json ##################json单对象######## ...

  4. Java文件选择对话框(文件选择器JFileChooser)的使用:以一个文件加密器为例

    文件加密器,操作过程肯定涉及到文件选择器的使用,所以这里以文件加密器为例.下例为我自己写的一个文件加密器,没什么特别的加密算法,只为演示文件选择器JFileChooser的使用. 加密器界面如图: 项 ...

  5. ResultSet rs = stmt.executeQuery(sql); 返回值问题判断

      JAVA  ResultSet rs = stmt.executeQuery(sql);  //查询返回的结果集不管是否查到,rs都不是null,那么问题是怎么判断查找不到来执行一个提示“账号或者 ...

  6. LLVM 笔记(一)—— phi 指令

    ilocker:关注 Android 安全(新手) QQ: 2597294287 语法: <result> = phi <ty> [ <val0>, <lab ...

  7. Stanford机器学习笔记-2.Logistic Regression

    Content: 2 Logistic Regression. 2.1 Classification. 2.2 Hypothesis representation. 2.2.1 Interpretin ...

  8. Eclipse较为常用快捷键

    今天在学习Eclipse的使用时,Mark了一些较为常用的快捷键,拿出来和大家分享一下: Ctrl+1 快捷修复 Ctrl+D 快捷删除行 Shift+Enter 在当前行任意位置光标跳转到下一行 C ...

  9. 这段时间对c#和java的感受

    这段时间对c#和java的感受 虽然很多书上说语法相似,但实际这是一个接近于门外汉的看法 真正的不同是 c#对更贴近系统API,      而java倡导跨平台 因而c#语法关键字更多,更细, 而ja ...

  10. java 22 - 7 多线程之控制线程的方法

    线程休眠(让线程休息一会再运行) public static void sleep(long millis) 在自定义线程类中添加该方法. 更改后,运行测试类,结果就是每执行完一轮,就休息1秒(这里设 ...