我有一个递归函数在MATLAB代码中选择如下:
function nk=choose(n, k)
if (k == 0)
nk=1;
else
nk=(n * choose(n - 1, k - 1)) / k;
end
end
该代码用于计算n和k之间的组合。我想通过使用mex代码来加速它。我试着写一个mex代码
double choose(double* n, double* k)
{
if (k==0)
return 1;
else
return (n * choose(n - 1, k - 1)) / k;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *n, *k, *nk;
int mrows, ncols;
plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
/* Assign pointers to each input and output. */
n = mxGetPr(prhs[0]);
k = mxGetPr(prhs[1]);
nk = mxGetPr(plhs[0]);
/* Call the recursive function. */
nk=choose(n,k);
}
然而,它不起作用。你能帮我修改一下可以实现上述MATLAB代码的mex代码吗?感谢
答案 0 :(得分:1)
不需要mex二项式系数可以在Matlab中实现:
function nk=nchoosek2(n, k)
if n-k > k
nk = prod((k+1:n) .* prod((1:n-k).^ (-1/(n-k))));
else
nk = prod((n-k+1:n) .* prod((1:k).^ (-1/k)) ) ;
end
end
答案 1 :(得分:1)
以下代码修复了您的C mex实现 问题不在于递归当然...... 您的代码使用指针而不是值(在C中,仅在正确的位置使用指针很重要)。
您可以使用Matlab内置功能:nchoosek
请参阅:http://www.mathworks.com/help/matlab/ref/nchoosek.html
以下代码有效:
//choose.c
#include "mex.h"
double choose(double n, double k)
{
if (k==0)
{
return 1;
}
else
{
return (n * choose(n - 1, k - 1)) / k;
}
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *n, *k, *nk;
int mrows, ncols;
plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL);
/* Assign pointers to each input and output. */
n = mxGetPr(prhs[0]);
k = mxGetPr(prhs[1]);
nk = mxGetPr(plhs[0]);
/* Call the recursive function. */
//nk=choose(n,k);
*nk = choose(*n, *k);
}
在Matlab中编译:
mex choose.c
执行:
choose(10,5)
ans =
252
这不是低效的实施......
我正在帮助修复你的实现,被用作“低效的例子”。
衡量rahnema1执行的执行情况:
tic; n = 1000000; k = 500000; nk = prod((k + 1:n)。* prod((1:n-k)。^( - 1 /(n-k)))); toc
经过的时间是0.022855秒。
衡量choose.mexw64实施的执行情况:
tic; n = 1000000; k = 500000; nk =选择(1000000,500000); toc
经过时间为0.007952秒
(花费的时间少于prod((k + 1:n)。* prod((1:n-k)。^( - 1 /(n-k)))))。
测量Matlab递归,得到误差(即使对于n = 700和k = 500):
ic; n = 700; k = 500; nk = RecursiveFunctionTest(n,k); toc
达到最大递归限制500。使用set(0,'RecursionLimit',N)更改限制。请注意,超出可用堆栈空间可以
崩溃MATLAB和/或您的计算机。
tic; n = 700; k = 400; nk = RecursiveFunctionTest(n,k); toc
经过的时间是0.005635秒。
非常低效......
测量Matlab内置函数nchoosek:
tic; nchoosek(1000000,500000); toc
警告:结果可能不准确。系数大于9.007199e + 15,仅精确到15位
在92岁的nchoosek
经过的时间是0.005081秒。
结论:
您需要在不使用递归的情况下实现C mex文件,并采取措施。
没有递归的测量:
static double factorial(double number)
{
int x;
double fac = 1;
if (number == 0)
{
return 1.0;
}
for (x = 2; x <= (int)number; x++)
{
fac = fac * x;
}
return fac;
}
double choose(double n, double k)
{
if (k == 0)
{
return 1.0;
}
else
{
//n!/((n–k)! k!)
return factorial(n)/(factorial(n-k)*factorial(k));
}
}
tic;choose(1000000, 500000);toc
经过的时间是0.003079秒。
更快...