带 mexCallMATLAB 的 Matlab mex 文件几乎比相应的 m 文件慢 300 倍

2023-11-27

我开始用 C++ 实现一些 m 文件以减少运行时间。 m 文件生成 n 维点并计算这些点处的函数值。这些函数是用户定义的,它们作为函数句柄传递到 m 文件和 mex 文件。 mex 文件使用 mexCallMATLAB 和 feval 来查找函数值。

我构建了下面的示例,其中在 Matlab 命令行中构建的函数句柄 fn 被传递到 matlabcallingmatlab.m 和 mexcallingmatlab.cpp 例程。使用新打开的 Matlab,mexcallingmatlab 在 241.5 秒内计算该函数 200000,而 matlabcallingmatlab 在 0.81522 秒内计算该函数,因此 mex 实现速度慢了 296 倍。这些时间是第二次运行的结果,因为第一次运行似乎更大,可能是由于第一次加载程序等相关的一些开销。

我花了很多天在网上搜索这个问题并尝试了一些建议。我尝试了不同的 mex 编译标志来优化 mex,但性能几乎没有差异。 Stackoverflow 中的上一篇文章指出升级 Matlab 是解决方案,但我在 Mac OS X 版本:10.8.4 上使用的可能是最新版本的 MATLAB 版本:8.1.0.604 (R2013a)。我确实使用和不使用 –largeArrayDims 标志编译了 mex 文件,但这也没有任何区别。有人建议函数句柄的内容可以直接在 cpp 文件中编码,但这是不可能的,因为我想向具有向量输入和实数输出的任何类型函数的任何用户提供此代码。

据我发现,mex 文件需要通过 feval 函数才能使用函数句柄,而 m 文件可以直接调用函数句柄,前提是 Matlab 版本比某些版本新。

任何帮助将不胜感激。

在 Matlab 命令行中创建的简单函数句柄:

fn = @(x) x'*x 

matlab调用matlab.m :

function matlabcallingmatlab( fn )
x = zeros(2,1); 
for i = 0 : 199999
    x(2) = i; 
    f = fn( x ); 
end

mexcallingmatlab.cpp:

#include "mex.h"
#include <cstring>

void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
    mxArray *lhs[1], *rhs[2]; //parameters to be passed to feval
    double f, *xptr, x[] = {0.0, 0.0}; // x: input to f and f=f(x)
    int n = 2, nbytes = n * sizeof(double);  // n: dimension of input x to f

    // prhs[0] is the function handle as first argument to feval
    rhs[0] = const_cast<mxArray *>( prhs[0] );

    // rhs[1] contains input x to the function
    rhs[1] = mxCreateDoubleMatrix( n, 1, mxREAL);
    xptr = mxGetPr( rhs[1] );

    for (int i = 0; i < 200000; ++i)
    {
        x[1] = double(i);   // change input 
        memcpy( xptr, x, nbytes );  // now rhs[1] has new x
        mexCallMATLAB(1, lhs, 2, rhs, "feval");
        f = *mxGetPr( lhs[0] );
    }
}

mex文件的编译:

>> mex -v -largeArrayDims mexcallingmatlab.cpp

所以我尝试自己实现这个,我想我找到了缓慢的原因。

基本上你的代码有一个小的内存泄漏,你没有释放lhs mxArray从调用返回mexCallMATLAB。这并不完全是内存泄漏,因为 MATLAB 内存管理器会在 MEX 文件退出时释放内存:

MATLAB 分配动态内存来存储mxArrays in plhs。 当您清除 MEX 文件时,MATLAB 会自动释放动态内存。 但是,如果堆空间非常宝贵,请调用mxDestroyArray什么时候 你已经完成了mxArrays plhs指着。

显式仍然比隐式好...所以你的代码确实给 MATLAB 内存管理器的释放器带来了压力:)

mexcallingmatlab.cpp

#include "mex.h"

#ifndef N
#define N 100
#endif

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    // validate input/output arguments
    if (nrhs != 1) {
        mexErrMsgTxt("One input argument required.");
    }
    if (mxGetClassID(prhs[0]) != mxFUNCTION_CLASS) {
        mexErrMsgTxt("Input must be a function handle.");
    }
    if (nlhs > 1) {
        mexErrMsgTxt("Too many output arguments.");
    }

    // allocate output
    plhs[0] = mxCreateDoubleMatrix(N, 1, mxREAL);
    double *out = mxGetPr(plhs[0]);

    // prepare for mexCallMATLAB: val = feval(@fh, zeros(2,1))
    mxArray *lhs, *rhs[2];
    rhs[0] = mxDuplicateArray(prhs[0]);
    rhs[1] = mxCreateDoubleMatrix(2, 1, mxREAL);
    double *xptr = mxGetPr(rhs[1]) + 1;

    for (int i=0; i<N; ++i) {
        *xptr = i;
        mexCallMATLAB(1, &lhs, 2, rhs, "feval");
        out[i] = *mxGetPr(lhs);
        mxDestroyArray(lhs);
    }

    // cleanup
    mxDestroyArray(rhs[0]);
    mxDestroyArray(rhs[1]);
}

MATLAB

fh = @(x) x'*x;
N = 2e5;

% MATLAB
tic
out = zeros(N,1);
for i=0:N-1
    out(i+1) = feval(fh, [0;i]);
end
toc

% MEX
mex('-largeArrayDims', sprintf('-DN=%d',N), 'mexcallingmatlab.cpp')
tic
out2 = mexcallingmatlab(fh);
toc

% check results
assert(isequal(out,out2))

运行上述基准测试几次(以热身),我得到以下一致的结果:

Elapsed time is 0.732890 seconds.    % pure MATLAB
Elapsed time is 1.621439 seconds.    % MEX-file

与您最初度过的缓慢时光相差甚远!不过,纯 MATLAB 部分的速度大约是原来的两倍,这可能是因为调用外部 MEX 函数的开销。

(我的系统:Win8运行64位R2013a)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

带 mexCallMATLAB 的 Matlab mex 文件几乎比相应的 m 文件慢 300 倍 的相关文章

随机推荐

  • 如何在 Nginx 上使用 FastCGI 防止网关超时

    我正在运行 Django FastCGI 和 Nginx 我正在创建一个 api 人们可以通过 XML 发送一些数据 我将处理这些数据 然后为发送过来的每个节点返回一些状态代码 问题是 如果我处理 XML 的时间太长 我认为超过 60 秒
  • 当我尝试使用 UI Automation for PowerPoint 2013 时,我只能在使用 RangeFromPoint 时获取第一个字符/单词

    该代码适用于 Word 和 Outlook 但不适用于 PowerPoint 因为仅选择文本框的第一个字符或第一个单词 这是一个错误吗 有什么解决方法吗 在 PowerPoint 2013 中的简单 PowerPoint 幻灯片上尝试此操作
  • IOMobileFramebufferGetLayerDefaultSurface 在 iOS 9 上不起作用

    我的主要问题是 如何对已经存在但在新版本的 iOS 中进行了修改的私有 API 函数进行逆向工程 我创建了一个 iOS 应用程序来使用 IOSurface 和 IOMobileFramebuffer 记录屏幕内容 帧缓冲区用于打开它的主要函
  • 如何从单个 Jenkins Pipeline 并行块获取 stdout 和 stderr?

    我正在使用一个parallel阻止到我的 Jenkinsfile 中同时执行一些测试 但所有输出都变得混乱 这是我的 Jenkinsfile 的摘录 例如 do some IT against different databases sta
  • 使用 ramda group by 属性并对指定属性求和结果

    我需要帮助使用 ramda 转换对象数组 我想 按指定属性分组 对另一个属性求和 结果集 给定一个像这样的数组 var arr title scotty age 22 score 54 hobby debugging title scott
  • 如何访问 GridSearchCV 中的 ColumnTransformer 元素

    当引用 grid search 的 param grid 中的 ColumnTransformer 它是管道的一部分 中包含的单个预处理器时 我想找出正确的命名约定 环境和样本数据 import seaborn as sns from sk
  • 将 Windows 时区转换为 moment.js 时区?

    我们在 ASP NET 中有一个应用程序 它以 Windows 格式存储所有用户时区数据 通过 TimeZoneInfo Id 我们还使用 moment js 和 moment js TimeZone 库将 UTC 数据转换为客户端的用户数
  • Gradle 没有以正确的方式寻找依赖关系

    我正在尝试将 moko 添加到 gradle 上的 kotlin multiplataform 的依赖项 org gradle internal resolve ArtifactNotFoundException 找不到 mvvm live
  • 什么是实体?为什么叫实体?

    在谈论实体框架时 什么是实体 它是数据存储的内存中表示 例如 SQL 表 实体足够聪明 可以跟踪更改并将这些更改应用到数据存储中 还有什么其他的吗 它来自系统工程领域 他们使用实体关系图设计系统的工具 他们所做的首先是布置实体 例如客户 采
  • 可以在 Javascript 中比较两个图像吗?

    有没有办法比较两个具有不同文件名的图像文件 所以我想看看它们是否与 javascript 相同 这可能吗 这样做的用途 我有一个图像库需要在灯箱中弹出 当灯箱打开时 我将连接到回调以检查重复的图像 并在找到时将它们从灯箱库中删除 这样用户就
  • 无法在 TypeScript 中从 Observable.bindNodeCallback(fs.readFile) 创建 observable

    我正在尝试使用rxjs 5用 TypeScript 编写 Node js 服务器 但在转换时遇到错误fs readFile其 rxjs 形式 我希望以下代码可以在 TypeScript 中运行 This is a JavaScript ex
  • 清除矩形不工作

    我正在用 javascript 做一个 Pong 游戏 以便学习制作游戏 并且我想让它面向对象 我无法得到clearRect上班 它所做的只是画一条越来越长的线 这是相关代码 function Ball this radius 5 this
  • 在C中将int转换为char

    现在我正在尝试在 C 编程中将 int 转换为 char 经过研究 我发现我应该能够这样做 int value 10 char result char value 我想要的是返回 A 0 9 返回 0 9 但我认为这会返回一个新行字符 我的
  • 如何检查变量或对象是否未定义?

    我一直以为我可以通过将未定义的变量与未定义的变量进行比较来检查它 但这是我在 chrome 控制台中收到的错误 我如何检查 jQuery 对象是否未定义 EDIT if jQuery 也给我带来了问题 EDIT 解决方案 if window
  • 使用 Google Analytics 进行 Flutter 日志事件

    我已经在我的 flutter 应用程序中设置了 Google Analytics 这一切似乎都按标准运行 数据通过并显示在分析控制台屏幕上 向用户显示 事件计数之类的事情 我看到默认事件是 user engagement screen vi
  • CakePHP 3.0 -> 查找条件之间

    是否可以执行 BETWEEN AND cakephp 2 5 中的条件类似于 cakephp 2 5 在 cakephp 2 5 中我写了类似的东西 conditions gt start date BETWEEN AND gt 2014
  • 如何使用 css 隐藏元素,同时仍将其保留在页面上?

    我试图隐藏页面上的一个元素 但我仍然希望它存在 我想要一个仍然可以单击的按钮 但我希 望它不可见 隐藏元素并保持页面位置的方法有3种 您可以获得有关之间的更多信息正常流量和css样式 即 opcity visibility 属性关系 能见度
  • java.lang.IllegalStateException:恢复下溢 - 恢复多于保存

    我在用rippleeffect library对于我的项目 但在Android Nougat and Marshmallow 应用程序因该库而崩溃 compile com github traex rippleeffect library
  • sqlite 将“dd.MM.yyyy”格式字符串转换为日期

    我的 android 上有一个 sqlite 数据库 其中有一个日期时间列 其中包含格式为 dd MM yyyy 的日期 这不是我的数据库 我无法更改日期格式 我想将数据库中的日期与代表第二个日期的字符串进行比较 但我尝试的一切都失败了 如
  • 带 mexCallMATLAB 的 Matlab mex 文件几乎比相应的 m 文件慢 300 倍

    我开始用 C 实现一些 m 文件以减少运行时间 m 文件生成 n 维点并计算这些点处的函数值 这些函数是用户定义的 它们作为函数句柄传递到 m 文件和 mex 文件 mex 文件使用 mexCallMATLAB 和 feval 来查找函数值