在Matlab中加速mex文件
我有一个大循环,我需要在我的代码中计算很多次,我认为使用MATLABcoder可以加速它。但是,我的代码的mex文件版本(函数的代码附在下面)最终比m文件慢。我使用MINGW64编译器编译了代码 我尝试了不同的编译器设置(使用coder.config)和不同的内存规范,但没有成功在Matlab中加速mex文件,matlab,Matlab,我有一个大循环,我需要在我的代码中计算很多次,我认为使用MATLABcoder可以加速它。但是,我的代码的mex文件版本(函数的代码附在下面)最终比m文件慢。我使用MINGW64编译器编译了代码 我尝试了不同的编译器设置(使用coder.config)和不同的内存规范,但没有成功 function v_d = test_code(q,v_exp,wealth,b_grid_choice,k_grid_choice,nz,nk,nb) %#codegen % Inputs % q is a
function v_d = test_code(q,v_exp,wealth,b_grid_choice,k_grid_choice,nz,nk,nb)
%#codegen
% Inputs
% q is an array of dimension [nz nk nb]
% v_exp is an array of dimension [nz nk nb]
% wealth is an array of dimension [nz nk nb]
% b_grid_choice is an array of dimension [nk nb]
% k_grid_choice is an array of dimension [nk nb]
% Typically, nz/nk/nb is an integer (currently up to 200)
v_d = coder.nullcopy(zeros(nz,nk,nb));
parfor ii = 1:nz
q_ini_ii = reshape(q(ii,:,:),[],nz);
v_ini_exp_ii = reshape(v_exp(ii,:,:),[],nz);
choice = q_ini_ii.*b_grid_choice - k_grid_choice;
for jj = 1:nk
for kk = 1:nb
% dividends at time t
d = wealth(ii,jj,kk) + choice;
% choosing optimal consumption
vec_d = d + v_ini_exp_ii.*(d>0);
v_d(ii,jj,kk) = max(vec_d,[],'all');
end
end
end
当我在nz
=nk
=nb
=100
运行此代码时,m文件需要2.5s,而生成的mex文件需要7.5s。我尝试使用MATLABcoder应用程序和codegen
命令
codegen -O enable:OpenMP test_code -args {q,v_exp,wealth,b_grid_choice,k_grid_choice,nz,nk,nb}
我还玩了codegen.config('mex')
,但对性能影响不大
当我测试上述代码的速度时,我只需使用
randn
命令生成这些矩阵,然后将它们传递到代码中。有趣的是,当我在函数中生成这些矩阵时,这对m文件的速度没有影响,但会将mex文件的速度提高近10倍(因此比m文件快3倍)!这对我来说意味着有一种方法可以加快代码的速度,但是尽管我努力了,我还是没能找到它。我认为内存分配可能是背后的原因,但我尝试使用动态内存规范也没有带来任何收益 为了加快代码的速度,将循环转过来:内部循环应该在第一个索引上,外部循环应该在最后一个索引上。这将按存储顺序处理数据,从而优化缓存使用。此外,手动编写的MEX文件可能比codegen
生成的文件快。@CrisLuengo感谢您的建议。不幸的是,更改循环顺序并没有提高性能。我想加快速度的唯一方法是在C++中编写这段代码,然后编译它而不是依赖于代码。这个代码是“大循环”还是这个函数经常被调用在“大循环”中?我不确定在mex函数中,parfor
是否是一个好主意(我甚至不知道这是否有效…)。它可能会在每次调用该函数时设置一个新池,从而导致开销。MATLAB代码可能更快,因为并行池仍然是open@max这段代码是一个“大循环”,但在实际代码中,它将在一个while循环内。现在,我只是想用我正在加速的函数的一部分来学习一些关于mex文件的知识。据我所知,parfor在墨西哥工作。当我使用-O disable:OpenMP关闭它时,mex代码的速度会大大降低(我还看到task manager中的CPU利用率很低)。我明白你关于matlab池的观点,但是当测试池被打开时,我总是可以在运行代码之前为它设置一个计时器,以便在循环运行时打开它。要加快代码的速度,请将循环转过来:内循环应该在第一个索引上,外循环应该在最后一个索引上。这将按存储顺序处理数据,从而优化缓存使用。此外,手动编写的MEX文件可能比codegen
生成的文件快。@CrisLuengo感谢您的建议。不幸的是,更改循环顺序并没有提高性能。我想加快速度的唯一方法是在C++中编写这段代码,然后编译它而不是依赖于代码。这个代码是“大循环”还是这个函数经常被调用在“大循环”中?我不确定在mex函数中,parfor
是否是一个好主意(我甚至不知道这是否有效…)。它可能会在每次调用该函数时设置一个新池,从而导致开销。MATLAB代码可能更快,因为并行池仍然是open@max这段代码是一个“大循环”,但在实际代码中,它将在一个while循环内。现在,我只是想用我正在加速的函数的一部分来学习一些关于mex文件的知识。据我所知,parfor在墨西哥工作。当我使用-O disable:OpenMP关闭它时,mex代码的速度会大大降低(我还看到task manager中的CPU利用率很低)。我明白你关于matlab池的观点,但是当测试池被打开时,我总是可以在运行代码之前为它设置一个计时器,以便在循环运行时打开它。