【问题标题】:Unable to detect why the following piece of code was not vectorized无法检测到以下代码未矢量化的原因
【发布时间】:2012-07-15 17:04:55
【问题描述】:

一段时间以来,我一直在努力对特定应用程序进行矢量化,并且我已经尝试了所有方法。从自动矢量化到手动编码的 SSE 内在函数。但不知何故,我无法在基于模板的应用程序上获得加速。

以下是我当前代码的 sn-p,我使用 SSE 内在函数对其进行了矢量化。当我使用 -vec-report3 编译 (Intel icc) 时,我不断收到以下消息:
remark: loop was not vectorized: statement cannot be vectorized.

  #pragma ivdep
  for ( i = STENCIL; i < z - STENCIL; i+=4 )
  {
    it = it2 + i;

    __m128 tmp2i = _mm_mul_ps(_mm_add_ps(_mm_load_ps(&p2[i+j*it_j-it_j4+k*it_k]),_mm_load_ps(&p2[i+j*it_j+it_j4+k*it_k])),X4_i); //loop was not vectorized: statement cannot be vectorized
    __m128 tmp3 = _mm_mul_ps(_mm_add_ps(_mm_load_ps(&p2[i+j*it_j-it_j3+k*it_k]),_mm_load_ps(&p2[i+j*it_j+it_j3+k*it_k])),X3_i);
    __m128 tmp4 = _mm_mul_ps(_mm_add_ps(_mm_load_ps(&p2[i+j*it_j-it_j2+k*it_k]),_mm_load_ps(&p2[i+j*it_j+it_j2+k*it_k])),X2_i);
    __m128 tmp5 = _mm_mul_ps(_mm_add_ps(_mm_load_ps(&p2[i+j*it_j-it_j +k*it_k]),_mm_load_ps(&p2[i+j*it_j+it_j +k*it_k])),X1_i);

    __m128 tmp6 = _mm_add_ps(_mm_add_ps(_mm_add_ps(tmp2i,tmp3),_mm_add_ps(tmp4,tmp5)), _mm_mul_ps(_mm_load_ps(&p2[it]),C00_i));

    _mm_store_ps(&tmp2[i],tmp6);

   }

我错过了什么重要的东西吗?由于消息没有详细说明为什么它不能被矢量化,我发现很难确定瓶颈。

更新: 在仔细考虑了这些建议后,我按照以下方式调整了代码。我认为最好将其进一步分解,以确定实际上导致向量依赖的语句。

//#pragma ivdep
  for ( i = STENCIL; i < z - STENCIL; i+=4 )
  {
    it = it2 + i;
    __m128 center = _mm_mul_ps(_mm_load_ps(&p2[it]),C00_i);

    u_j4 = _mm_load_ps(&p2[i+j*it_j-it_j4+k*it_k]); //Line 180
    u_j3 = _mm_load_ps(&p2[i+j*it_j-it_j3+k*it_k]);
    u_j2 = _mm_load_ps(&p2[i+j*it_j-it_j2+k*it_k]);
    u_j1 = _mm_load_ps(&p2[i+j*it_j-it_j +k*it_k]);
    u_j8 = _mm_load_ps(&p2[i+j*it_j+it_j4+k*it_k]);
    u_j7 = _mm_load_ps(&p2[i+j*it_j+it_j3+k*it_k]);
    u_j6 = _mm_load_ps(&p2[i+j*it_j+it_j2+k*it_k]);
    u_j5 = _mm_load_ps(&p2[i+j*it_j+it_j +k*it_k]);

    __m128 tmp2i = _mm_mul_ps(_mm_add_ps(u_j4,u_j8),X4_i);
    __m128 tmp3 = _mm_mul_ps(_mm_add_ps(u_j3,u_j7),X3_i);
    __m128 tmp4 = _mm_mul_ps(_mm_add_ps(u_j2,u_j6),X2_i);
    __m128 tmp5 = _mm_mul_ps(_mm_add_ps(u_j1,u_j5),X1_i);

    __m128 tmp6 = _mm_add_ps(_mm_add_ps(tmp2i,tmp3),_mm_add_ps(tmp4,tmp5));
    __m128 tmp7 = _mm_add_ps(tmp6,center);

    _mm_store_ps(&tmp2[i],tmp7);  //Line 196

   }

当我在没有#pragma ivdep 的情况下编译(icc)上述代码时,我收到以下消息:

remark: loop was not vectorized: existence of vector dependence.
vector dependence: assumed FLOW dependence between tmp2 line 196 and tmp2 line 196.
vector dependence: assumed ANTI dependence between tmp2 line 196 and tmp2 line 196.

当我使用 #pragma ivdep 编译 (icc) 时,我收到以下消息:

remark: loop was not vectorized: unsupported data type. //Line 180

为什么建议第 196 行有依赖关系?如何消除建议的向量依赖性?

【问题讨论】:

  • 通过预先计算结束值和循环数来简化for 构造。
  • 它不能向量化它,因为你已经向量化了它。你没有得到任何加速,因为你的计算/内存访问比率太低了。
  • 这不是我最初想到的对齐方式(Mysticial 纠正了我),但从简化数组偏移的表达式开始绝对值得。
  • 这不是问题。您只有 13 次操作有 10 次内存访问。这太多了。 CPU 可能会因负载而不是计算而成为瓶颈。根据我的经验,您确实需要至少 3 比 1 的计算/内存访问比率。
  • 减少内存访问的唯一方法是改变处理数据的方式。如果您对同一数据进行多次传递,请尝试将它们组合在一起。在这里我能说的不多了。你可以看看:en.wikipedia.org/wiki/Loop_tiling

标签: c sse vectorization icc stencils


【解决方案1】:

问题是您正在尝试将自动矢量化与手动矢量化代码一起使用。编译器说该行不能向量化,因为你不能向量化向量函数。

要么让编译器自动矢量化它,要么禁用自动矢量化并手动矢量化您的代码。正如已经评论过的那样,自动矢量化器将计算矢量化的盈利能力:它会检查是否值得对您的代码进行矢量化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 2020-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多