【发布时间】:2018-02-24 23:25:03
【问题描述】:
我正在尝试执行诸如乘以具有 3200 万个元素的 7D 数组之类的操作。我写了一个 MEX 文件,因为我的印象是这些操作在 C 中应该比在 Matlab 中更快。但是,我发现 MEX 文件的速度大约是直接在 Matlab (2017b) 中执行操作的两倍。
我要执行的示例操作是:
T8 = rand(1,1e3,2,2,2,2,2);
wsm = rand(1e3,1e3,2,2);
CM = bsxfun(@times,T8,wsm);
在我的机器上,这需要 0.117065 秒(我称此操作和其他类似操作,每次运行模型约 1000 次,并且模型运行数千次以优化参数 - 这些操作使优化变得非常缓慢)。
这是我编写的 MEX 文件,它使用 7 个 for 循环通过线性索引访问 T8 和 wsm 的元素(也许我应该以更有效的方式访问元素或避免 for 循环?):
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mwSize i, j, k, l, m, n, o, I, J, K, L, M, N, O;
mwSize *dims,*dims1;
double *T8, *wsm, *CM;
T8 = mxGetPr(prhs[0]);
wsm = mxGetPr(prhs[1]);
dims = mxGetDimensions(prhs[0]);
dims1 = mxGetDimensions(prhs[1]);
dims[0] = dims1[0];
I = dims[0];
J = dims[1];
K = dims[2];
L = dims[3];
M = dims[4];
N = dims[5];
O = dims[6];
plhs[0] = mxCreateNumericArray(7,dims,mxDOUBLE_CLASS,mxREAL);
CM = mxGetPr(plhs[0]);
for( o=0; o<O; o++ ) {
for( n=0; n<N; n++ ) {
for( m=0; m<M; m++ ) {
for( l=0; l<L; l++ ) {
for( k=0; k<K; k++ ) {
for( j=0; j<J; j++ ) {
for( i=0; i<I; i++ ) {
*CM++ = T8[j + k*J + +l*J*K + m*L*J*K + n*M*L*J*K + o*N*M*L*J*K] * wsm[i + j*I + k*I*J + l*I*J*K];
}
}
}
}
}
}
}
}
当我调用上面的 MEX 文件时
CM = arrayProduct(T8,wsm);
需要 0.215211 秒(几乎是原来的两倍)。
我的代码非常松散地基于此处建议的代码 (https://uk.mathworks.com/matlabcentral/answers/210352-optimize-speed-up-a-big-and-slow-matrix-operation-with-addition-and-bsxfun)。
任何关于我可以做些什么来加快我的代码速度的建议将不胜感激!
【问题讨论】:
-
您可以从将计算移出最内层循环开始。您可以考虑的另一件事是,在 C 中,array[m][n] 实际上是 array[m*n](将其外推到 n 维)。当最内层循环访问不连续的元素时,您可能会不断地破坏您的缓存。如果您可以获得顺序数据,那么您可以使用内部 simd 指令进行一些并行处理。
-
啊,但是你真的能在做矩阵的事情上打败一个叫做 MATrix LABoratory 的软件吗?您选择了一场非常糟糕的战斗:D 并且考虑到您正在做幼稚的矩阵乘法,甚至没有 a fast version
标签: c optimization compiler-optimization mex