【问题标题】:Optimize MEX file to speed up multiplication of large multidimensional arrays (code bottleneck)优化MEX文件,加速大型多维数组的乘法(代码瓶颈)
【发布时间】: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


【解决方案1】:

假设您可以在这样的微不足道的矩阵数学中击败 Matlab,这是一个大错误。 Matlab 从一开始就进行了优化,可以进行矩阵数学运算。

有时编写 MEX 函数有充分的理由,包括出于性能原因,但这通常是在纯 Matlab 解决方案无法以最佳方式编写的情况下(例如,当您需要编写大量显式循环时) .

您的代码可能比 Matlab 中已经存在的优化矩阵数学慢的两个主要原因是:

  1. Matlab 可能使用多个线程并行进行计算。您的代码不会,但真正的最佳解决方案可能会。
  2. 您可能在内存访问模式中犯了错误,导致缓存命中率降低。

另一种看待这个问题的方式是:如果不能信任 Matlab 以最佳方式实现乘法,人们会使用它在大型数据集上进行严肃的数学运算吗?有些算法 Matlab 不知道,有时可以使用 MEX 加速,但乘法不是其中之一。

【讨论】:

    猜你喜欢
    • 2013-02-25
    • 2015-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 2011-08-24
    相关资源
    最近更新 更多