【问题标题】:Optimize the calculation of correlation matrix优化相关矩阵的计算
【发布时间】:2012-02-27 00:53:32
【问题描述】:

下面的代码计算给定协方差矩阵的相关矩阵。我怎样才能写得更好?问题是这部分代码将在尺寸约为 100 x 100 的矩阵上运行 1000 次。

// Copy upper triangle of covariance matrix to correlation matrix
for(i = 0; i < rows; i++){
  for(j = i; j < rows; j++){
    corrmatrix.array[i * rows + j] = covmatrix.array[i * rows + j];
  }
}

// Calculate upper triangle of corr matrix
for(i = 0; i < rows; i++){

  root = sqrt(covmatrix.array[(i * rows) + i]);    

  for(j = 0; j <= i; j++){ // Move down 
    corrmatrix.array[ j * rows + i ] /= root;
  }

  k = i * rows;

  for(j = i; j < rows; j++){ // Move across
    corrmatrix.array[ k + j ] /= root;
  }

}

// Copy upper triangle to lower triangle
for(i = 0; i < rows; i++){
  k = i * rows;
  for(j = i; j < rows; j++){
    corrmatrix.array[ (j * rows) + i ] = corrmatrix.array[ k + j ];
  }
}

我已经检查了行和列是否相等等,所以我只是在任何地方都使用行。我想优化速度(显着)。

PS:

  1. 矩阵以行优先的密集格式存储
  2. 我暂时不使用打包存储。

谢谢

【问题讨论】:

    标签: c performance numerical


    【解决方案1】:

    首先让我感到惊讶的是,您在内部循环中除以相同的数字。

    不要那样做。除法很慢。

    你应该做的是乘以root的倒数,而不是重复除以它:

    inv_root = 1. / sqrt(covmatrix.array[(i * rows) + i]);
    
    for(j = 0; j <= i; j++){ // Move down 
        corrmatrix.array[ j * rows + i ] *= inv_root;
    }
    
    k = i * rows;
    
    for(j = i; j < rows; j++){ // Move across
        corrmatrix.array[ k + j ] *= inv_root;
    }
    

    尽管这种优化对编译器来说似乎很明显,但由于浮点严格性,它可能不允许进行这种优化。您可以尝试使用 -ffast-math(在 GCC 中)或类似的东西来放松您的浮点设置。

    【讨论】:

    • 谢谢,我会添加更改。我还能做更多优化吗?
    • 没有什么是容易的。根据您的编译器,它可能能够为您矢量化它。除此之外,代码可能会受到您执行的大量内存访问的限制。解决这个问题的唯一方法是重构算法——这可能容易也可能不容易。
    猜你喜欢
    • 1970-01-01
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    相关资源
    最近更新 更多