是否可以避免 for 循环来计算矩阵条目

Is it possible to avoid the for-loop to compute matrix entries?

本文关键字:计算 可以避免 for 循环 是否      更新时间:2023-10-16

我必须使用嵌套的for循环来计算Eigen::MatrixXd类型矩阵输出的条目。这里 input[0]、input[1] 和 input[2] 被定义为 Eigen::ArrayXXd,以便使用元素运算。这部分似乎是我代码的瓶颈。谁能帮我加速这个循环?谢谢!

 for (int i = 0; i < r; i++) {
    for (int j = 0; j < r; j++) {
      for (int k = 0; k < r; k++) {
        output.col(i * (r * r) + j * r + k) =
            input[0].col(i) * input[1].col(j) * input[2].col(k);
      }
    }
  }

在考虑优化 for 循环的代码时,思考"是否有我可以消除的冗余计算?

请注意,在最内部的循环中,只有k在变化。您应该将所有涉及k的可能计算移出该循环:

for (int i = 0; i < r; i++) {
  int temp1 = i * (r * r);
  for (int j = 0; j < r; j++) {
    int temp2 = j * r;
    for (int k = 0; k < r; k++) {
      output.col(temp1 + temp2 + k) =
          input[0].col(i) * input[1].col(j) * input[2].col(k);
    }
  }
}

请注意i * (r * r)是如何一遍又一遍地计算的,但答案总是相同的!您只需在i增量时重新计算此值。j * r也是如此.

希望这有帮助!

要减少翻牌次数,您应该缓存 input[0]*input[1] 的结果:

ArrayXd tmp(input[0].rows());
for (int i = 0; i < r; i++) {
 for (int j = 0; j < r; j++) {
  tmp = input[0].col(i) * input[1].col(j);
  for (int k = 0; k < r; k++) {
    output.col(i * (r * r) + j * r + k) = tmp * input[2].col(k);
  }
 }
}

然后,要充分利用您的 CPU,请启用具有 -march=native 的 AVX/FMA,当然还有编译器优化 (-O3 (。

然后,

要了解您可以获得更多收益,请准确测量该部分所花费的时间,计算乘法次数(r^2*(n+r*n((,然后计算您每秒实现的浮点运算数。然后将其与 CPU 的容量进行比较。如果你很好,那么唯一的选择是使用多线程一个for循环,例如OpenMP。选择哪个 for 循环取决于输入的大小,但您可以尝试使用外部循环,确保每个线程都有自己的tmp数组。