我想将一个小次数的多项式 (2-5) 应用于长度可以在 50 到 3000 之间的向量,并尽可能高效地执行此操作。示例:例如,我们可以取函数:(1+x^2)^3,当x>3时,当x<=3时为0。对于双元素向量,这样的函数将执行 100k 次。每个向量的大小可以在 50 到 3000 之间。
一种想法是使用 Eigen: Eigen::ArrayXd v; 然后简单地应用一个仿函数: v.unaryExpr([&](double x) {return x>3 ? std::pow((1+x*x), 3.00) : 0.00;});
尝试使用 GCC 9 和 GCC 10,我发现这个循环没有被矢量化。我确实手动对其进行了矢量化,结果发现增益比我预期的要小得多(1.5 倍)。我还用逻辑 AND 指令替换了条件,基本上执行两个分支并在 x<=3 时将结果归零。我认为收益主要来自缺乏分支错误预测。
一些考虑 因素有多种因素在起作用。首先,我的代码中有 RAW 依赖项(使用内在函数)。我不确定这如何影响计算。我用 AVX2 编写了我的代码,所以我期待 4 倍的增益。我认为这起到了一定的作用,但我不能确定,因为 CPU 有无序处理。另一个问题是我不确定我尝试编写的循环的性能是否受内存带宽的限制。
问题 如何确定内存带宽或管道危害是否影响此循环的实现?我在哪里可以学习更好地矢量化这个循环的技术?Eigenr MSVC 或 Linux 中是否有用于此目的的好工具?我使用的是 AMD CPU,而不是 Intel。