【问题标题】:Why does GCC not auto-vectorize this loop?为什么 GCC 不自动矢量化这个循环?
【发布时间】:2011-12-29 23:03:02
【问题描述】:

我正在尝试优化占用我程序大量计算时间的循环。

但是当我使用 -O3 -ffast-math -ftree-vectorizer-verbose=6 打开自动矢量化时,GCC 输出它无法矢量化循环。

我使用的是 GCC 4.4.5

代码:

/// Find the point in the path with the largest v parameter
void prediction::find_knife_edge(
    const float * __restrict__ const elevation_path,
    float * __restrict__ const diff_path,
    const float path_res,
    const unsigned a,
    const unsigned b,
    const float h_a,
    const float h_b,
    const float f,
    const float r_e,
) const
{
    float wavelength = (speed_of_light * 1e-6f) / f;

    float d_ab = path_res * static_cast<float>(b - a);

    for (unsigned n = a + 1; n <= b - 1; n++)
    {
        float d_an = path_res * static_cast<float>(n - a);
        float d_nb = path_res * static_cast<float>(b - n);

        float h = elevation_path[n] + (d_an * d_nb) / (2.0f * r_e) - (h_a * d_nb + h_b * d_an) / d_ab;
        float v = h * std::sqrt((2.0f * d_ab) / (wavelength * d_an * d_nb));

        diff_path[n] = v;
    }
}

来自 GCC 的消息:

note: not vectorized: number of iterations cannot be computed.
note: not vectorized: unhandled data-ref 

在关于自动矢量化的页面 (http://gcc.gnu.org/projects/tree-ssa/vectorization.html) 上声明它支持未知循环边界。

如果我将 for 替换为

for (unsigned n = 0; n <= 100; n++)

然后它向量化它。

我做错了什么?

缺乏关于这些消息的确切含义的详细文档以及 GCC 自动矢量化的来龙去脉相当烦人。

编辑:

感谢大卫,我将循环更改为:

 for (unsigned n = a + 1; n < b; n++)

现在 GCC 尝试对循环进行矢量化但抛出此错误:

 note: not vectorized: unhandled data-ref
 note: Alignment of access forced using peeling.
 note: Vectorizing an unaligned access.
 note: vect_model_induction_cost: inside_cost = 1, outside_cost = 2 .
 note: not vectorized: relevant stmt not supported: D.76777_65 = (float) n_34;

“D.76777_65 = (float) n_34;”是什么意思?什么意思?

【问题讨论】:

  • IIRC,tree-ssa 是一个正在开发的新工具,用于克服 gcc 向量化器的限制,我认为它目前没有在 gcc 主干上使用。
  • n &lt;= b - 1 更改为n &lt; b
  • 我很确定我的 GCC 有 tree-ssa,否则它会抱怨不支持 -ftree-vectorizer-verbose 标志。
  • 大卫:这有效...但是我现在遇到一个新错误...我会更新问题。

标签: c++ gcc vectorization


【解决方案1】:

我可能稍微搞砸了细节,但这是您需要重组循环以使其矢量化的方式。诀窍是预先计算迭代次数并从 0 迭代到该数字的一个短值。不要更改for 语句。您可能需要修复它之前的两行和循环顶部的两行。他们大约是对的。 ;)

const unsigned it=(b-a)-1;
const unsigned diff=b-a;
for (unsigned n = 0; n < it; n++)
{
    float d_an = path_res * static_cast<float>(n);
    float d_nb = path_res * static_cast<float>(diff - n);

    float h = elevation_path[n] + (d_an * d_nb) / (2.0f * r_e) - (h_a * d_nb + h_b * d_an) / d_ab;
    float v = h * sqrt((2.0f * d_ab) / (wavelength * d_an * d_nb));

    diff_path[n] = v;
}

【讨论】:

  • 那行得通。谢谢。但是我现在需要弄清楚如何将索引设为数组中的最大值...
猜你喜欢
  • 2011-06-28
  • 2014-01-10
  • 1970-01-01
  • 2019-06-06
  • 2020-12-11
  • 2016-06-03
  • 2019-04-12
  • 2019-04-05
  • 2018-12-16
相关资源
最近更新 更多