【问题标题】:Preparing a Matrix in C++ for Matlab用 C++ 为 Matlab 准备一个矩阵
【发布时间】:2013-10-24 13:04:31
【问题描述】:

我有一个维度为 dim*dim 的稀疏矩阵 P 作为指针通过

double* P

/* create the output matrix */
plhs[0] = mxCreateDoubleMatrix(dim,dim,mxREAL);

/* get a pointer to the real data in the output matrix*/
P = mxGetPr(plhs[0]);

我在 mex 文件中执行此操作,因为我需要大量的 for 循环来填充 P 并且 c++ 比 matlab 快得多。

目前,dim=22500,c++ 填充 P 大约需要 2 秒(使用 matlab,此任务需要 50 秒),大约 100 秒在 matlab 中标准化矩阵,再次需要 100 秒来擦除所有零列在matlab中。我在 matlab 中使用以下代码执行此操作:

for i=1:size(P,1)
    if sum(P(i,:)) > 0
        sum(P(i,:))
        P(i,:)=(1/sum(P(i,:))).*P(i,:);
    end
end

% clear empty rows and colunms
P(~any(P,2),:)=[];
P(:,~any(P))=[];

我现在的问题是:我也可以在 c++ 中执行此操作吗?我尝试通过以下方式在 C++ 中规范化 P:

int i;
int j;
int sum;
int get_idx(int x, int y, int rows) {
   return x +y * rows;   
}
/* NORMALIZE */
for(i = 0; i <dim; i++)  {
    sum=0;
    for(j=0; j<dim;j++) {   
        sum = sum + P[get_idx(i,j,dim)];
    }
    if(sum > 0) {
         for(j=0; j<dim;j++) {   
           P[get_idx(i,j,p_rows)]=P[get_idx(i,j,dim)]*(1/sum);
        }
    }
}

但由于某种原因,这段代码似乎没有改变 P,而且在 c++ 中这需要大约 85 秒。有没有更快的方法也有效?另外,是否可以清除空行和空列?

【问题讨论】:

  • 对于您的 c++ 代码:sum 应该是双精度

标签: c++ performance matlab matrix


【解决方案1】:

为什么选择 C++?

在规范化之前清除空行/列 - 您不需要规范化空条目。

向量化归一化:

s = sum(P, 2);
valid = s > 0;
P( valid,: ) = bsxfun(@rdivide, P(valid,:), s(valid) );

哒哒!

太有趣了!


更新:关于减少行/列。
经过短暂的调查,我认为有一个〜x3的速度因素可以获得:

考虑以下三个选项:

  1. P( ~any(P,2), :) = []; P( :, ~any(P,1) ) = [];
  2. P( :, ~any(P,1) ) = []; P( ~any(P,2), :) = [];
  3. P = P( any(P,2), any(P,1) );

测试这三个备选方案,您会发现第三个备选方案要快约 3 倍,而第一个方案比第二个方案稍慢(但始终)。

为什么?
如果您还记得,Matlab 以列优先的方式将 matices 存储在内存中,因此在行之前消除列可以节省一些复制和重新分配内存。

然而,第一种和第二种选择复制和重新分配内存两次:一次用于行,一次用于列,而第三种选择只占用一次内存!

【讨论】:

  • 哇!我使用我的 for 循环来规范化它(实际上我使用 bsxfun(@rdivide, P(valid,:), s(valid) );) 并且它更快!而不是 100 秒来标准化它,现在只需要 2 秒。谢谢你。尽管如此,我摆脱所有零条目的部分仍在减慢一切。你有什么建议我可以加快速度吗?我应该使用 matlab 还是 c++ 来做到这一点?
  • @Adam:减小矩阵的大小是一项代价高昂的操作——它需要重新分配内存并复制许多元素以使生成的矩阵适合内存中的单个块。使用profile 来检查这部分代码。
  • @Adam - 你可以看到我关于从P删除行/列的更新
  • 非常感谢。但即使快了 3 倍,仍然是 33 秒。我已经重写了我的整个代码,以避免编写一个包含零行的矩阵。现在一切只需要大约 1 秒,我没问题。非常感谢:)
猜你喜欢
  • 2015-06-16
  • 2015-05-20
  • 1970-01-01
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多