找回密码
 注册
Simdroid-非首页
查看: 239|回复: 6

Mex程序简单示例

[复制链接]
发表于 2005-9-23 18:32:17 | 显示全部楼层 |阅读模式 来自 北京东城
前几天看到网上有人找一个程序,需要查询一个数组当中最大的几个值。也有人给出了用sort函数排序以后来查找的办法,我觉得不太合适,就写了一个C-Mex的程序来实现这个目的。我也是开始写C-Mex的程序,也当一个给入门的人的一个简单范例了。下面简单讲一下过程,高手见笑了!所有函数和源程序放在附件当中

nmax(x,n)        找数组当中最大的n个元素
nthmax(x,n)     找数组当中第n大的元素
nmin(x,n)         找数组当中最小的n个元素
nthmin(x,n)      找数组当中第n小的元素

在n比较小的时候运算比使用matlab的函数快
找最大或者最小值的时候比使用max或者min函数快,原因估计是Matlab的max和min函数完成的功能不仅仅是找出最大最小值。

首先需要使用配置Matlab的编译器,我没有安装其他的编译器,就是用的Matlab的编译器。命令:
mex -setup
然后就可以写C程序,完成以后使用
mex myfun.c
进行编译。

下面是实现我提到的目的的函数

#include "mex.h"
/*================================================*/
/*  冒泡法计算向量中最大的N个元素             */
/*                     */
/*  Author: WaitingForMe               */
/*  Email:   heroaq_2002@163.com             */
/*  Blog:   http://waitingforme.yculblog.com   */
/*================================================*/

/*计算程序,返回最大值的n个值,放在数组y当中,算法是冒泡法*/

void mexNMax(double y[], double x[], int N, int L)
{
    int i=0;
    int j=0;
    double temp;
    for(j=0;j<N;j++)
    {
        for(i=0;i<L-j-1;i++)
        {
            if(x>x[i+1])
            {
                temp=x[i+1];
                x[i+1]=x;
                x=temp;
            }
        }
    }
    for(i=0;i<N;i++)
    {
        y=x[L-1-i];
    }
    return;
}

/*Mex接口函数,实现Matlab到C的输入输入变量的传递*/
/*void mexFunction(输出变量个数,输出变量指针,输入变量个数,输入变量指针)*/
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    double *x, *y, *N;
    int L,mrows1,ncols1;

   /*检查输入输入变量个数是否合法*/
    if(nrhs!=2)
        mexErrMsgTxt("Two input arguments required!");
    else
        if(nlhs>1)
            mexErrMsgTxt("Too many output arguments");

    /*检查输入输入变量类型是否合法*/
     L=mxGetN(prhs[0]);
     if(!mxIsDouble(prhs[0])||mxIsComplex(prhs[0])||L==1)
        mexErrMsgTxt("The first input must be a col vector!");
     mrows1=mxGetM(prhs[1]);
     ncols1=mxGetN(prhs[1]);
     if(!mxIsDouble(prhs[0])||mxIsComplex(prhs[0])||mrows1!=1||ncols1!=1)
        mexErrMsgTxt("The second input argument must be an integer!");
     
     /*获取输入变量的指针*/
     x=mxGetPr(prhs[0]);
     N=mxGetPr(prhs[1]);
     
     /*建立输出矩阵变量*/
     plhs[0]=mxCreateDoubleMatrix(1,*N,mxREAL);
     /*将指针地址放在指针变量y当中*/
     y=mxGetPr(plhs[0]);
     
     /*检查返回最大个数是否比数组长度长,如果是就报错*/
     if(*N>L)
        mexErrMsgTxt("The number you want is greater than the length of input vector!");
     /*调用函数*/
     mexNMax(y, x, *N, L);
     return;
}

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

×
发表于 2005-9-23 20:47:38 | 显示全部楼层 来自 上海

Re:Mex程序简单示例

Simdroid开发平台
先谢后学!
发表于 2007-12-12 21:21:29 | 显示全部楼层 来自 大连理工大学
怎么还有密码 阿
回复 不支持

使用道具 举报

发表于 2007-12-15 11:57:30 | 显示全部楼层 来自 四川成都

顶顶顶顶顶顶顶顶顶顶

评分

1

查看全部评分

回复 不支持

使用道具 举报

发表于 2012-8-25 17:54:44 | 显示全部楼层 来自 北京
本帖最后由 rocwoods 于 2012-8-25 18:00 编辑

老瓶装新酒,邓兄发的帖子差不多7年了,其中MATLAB在发展,论坛也几经改版,邓兄代码的一些符号都成乱码了。重新梳理并在MATLAB 2011b中编译测试了下。
  1. #include "mex.h"
  2. /*================================================*/
  3. /*冒泡法计算向量中最大的N个元素       */
  4. /                                                            */
  5. /Author: WaitingForMe         */
  6. /*Email:   heroaq_2002@163.com         */
  7. /*Blog: http://waitingforme.yculblog.com   */
  8. /*================================================*/

  9. /*计算程序,返回最大值的n个值,放在数组y当中,算法是冒泡法*/

  10. void mexNMax(double y[], double x[], int N, int L)
  11. {
  12.     int i=0;
  13.     int j=0;
  14.     double temp;
  15.     for(j=0;j<N;j++)
  16.     {
  17.         for(i=0;i<L-j-1;i++)
  18.         {
  19.             if(x[i]>x[i+1])
  20.             {
  21.                 temp=x[i+1];
  22.                 x[i+1]=x[i];
  23.                 x[i]=temp;
  24.             }
  25.         }
  26.     }
  27.     for(i=0;i<N;i++)
  28.     {
  29.         y[i]=x[L-1-i];
  30.     }
  31.     return;
  32. }

  33. /*Mex接口函数,实现Matlab到C的输入输入变量的传递*/
  34. /*void mexFunction(输出变量个数,输出变量指针,输入变量个数,输入变量指针)*/
  35. void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
  36. {
  37.     double *x, *y, *N;
  38.     int L,mrows1,ncols1;

  39.    /*检查输入输入变量个数是否合法*/
  40.     if(nrhs!=2)
  41.         mexErrMsgTxt("Two input arguments required!");
  42.     else
  43.         if(nlhs>1)
  44.             mexErrMsgTxt("Too many output arguments");

  45.     /*检查输入输入变量类型是否合法*/
  46.      L=mxGetN(prhs[0]);
  47.      if(!mxIsDouble(prhs[0])||mxIsComplex(prhs[0])||L==1)
  48.         mexErrMsgTxt("The first input must be a col vector!");
  49.      mrows1=mxGetM(prhs[1]);
  50.      ncols1=mxGetN(prhs[1]);
  51.      if(!mxIsDouble(prhs[0])||mxIsComplex(prhs[0])||mrows1!=1||ncols1!=1)
  52.         mexErrMsgTxt("The second input argument must be an integer!");
  53.      
  54.      /*获取输入变量的指针*/
  55.      x=mxGetPr(prhs[0]);
  56.      N=mxGetPr(prhs[1]);
  57.      
  58.      /*建立输出矩阵变量*/
  59.      plhs[0]=mxCreateDoubleMatrix(1,*N,mxREAL);
  60.      /*将指针地址放在指针变量y当中*/
  61.      y=mxGetPr(plhs[0]);
  62.      
  63.      /*检查返回最大个数是否比数组长度长,如果是就报错*/
  64.      if(*N>L)
  65.         mexErrMsgTxt("The number you want is greater than the length of input vector!");
  66.      /*调用函数*/
  67.      mexNMax(y, x, *N, L);
  68.      return;
  69. }
复制代码
由于测试电脑没有装别的编译器,用的2011b的lcc,所以编译的时候需要去掉中文注释才能成功。
经过测试发现在2011b下结论和邓兄当时MATLAB版本下的大相径庭。
这个mex函数求最小值和最大值速度大概比MATLAB的min或者max慢10倍左右。对于1个1*1e7的随机向量,求最大(小)前10个值的速度已经和MATLAB的sort耗时相当了。(大概百倍时间于min和max函数)
结论:
对于一个长为N的向量求最大(小)的前n个值,如果N很大,n不是很大的话,在当前MATLAB环境下个人推荐的方法是:用n次min或max函数,每找到一个值,将找到的值置为inf或者-inf。如果n较大,(这个大的程度可以事先测试下),直接用sort函数比较合适。不过,邓兄这个mex函数是mex函数编程很好的一个示例。
回复 不支持

使用道具 举报

发表于 2012-8-25 19:43:57 | 显示全部楼层 来自 江苏南京
rocwoods 发表于 2012-8-25 17:54
老瓶装新酒,邓兄发的帖子差不多7年了,其中MATLAB在发展,论坛也几经改版,邓兄代码的一些符号都成乱码了 ...

这个估计是算法问题吧

用冒泡法来做太粗暴了,时间复杂度是O(N^2)
而matlab的max或min的时间复杂度是O(N)的

如果用quicksort的算法来做,可以做到O(N)实现,这样的话可以比sort(时间复杂度是O(N log N))快
回复 不支持

使用道具 举报

发表于 2012-8-25 21:04:42 | 显示全部楼层 来自 北京
本帖最后由 rocwoods 于 2012-8-25 21:14 编辑
ithinksoim 发表于 2012-8-25 19:43
这个估计是算法问题吧

用冒泡法来做太粗暴了,时间复杂度是O(N^2)


嗯,算法问题是主要原因,除此之外,MATLAB函数调用效率的提高也是一方面,以前老版本MATLAB循环慢,就是因为函数解释花得时间过长,导致MATLAB本身算法的优化体现不明显。可以肯定得是,像sort这样基本的函数,MATLAB肯定是做了大量优化的,而且这种优化应该是针对各种情况下排序算法的一种折中。
不过楼主的问题是找N个数中最大(小)的k个数,似乎是没有O(N)的算法的,应该有O(N*log(k))的算法。
回复 不支持

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

Simapps系列直播

Archiver|小黑屋|联系我们|仿真互动网 ( 京ICP备15048925号-7 )

GMT+8, 2024-10-2 02:51 , Processed in 0.040811 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表