【问题标题】:how can I get clang to vectorize a simple loop?如何让 clang 向量化一个简单的循环?
【发布时间】:2019-08-27 22:31:26
【问题描述】:

我有以下循环:

float* s;
float* ap;
float* bp;

... // initialize s, ap, bp

for(size_t i=0;i<64;++i) {
   s[i] = ap[i]+bp[i];
}

似乎是一个很好的矢量化候选者。虽然我打开了优化,但当我查看程序集输出时,clang(我正在使用 Xcode)似乎没有对循环进行矢量化:

LBB33_1:                                ## =>This Inner Loop Header: Depth=1
    movss   (%rax,%rsi,4), %xmm0    ## xmm0 = mem[0],zero,zero,zero
    addss   (%rcx,%rsi,4), %xmm0
    movss   %xmm0, (%rdx,%rsi,4)
Ltmp353:
    incq    %rsi
Ltmp354:
    cmpq    $64, %rsi
Ltmp355:
    jne LBB33_1

如何让 clang/Xcode 向量化这个简单的循环?

【问题讨论】:

  • 您是否尝试过使用float *restrict s 以便它知道输出不会与输入重叠?如果迭代次数很少,它可能会决定不值得发出代码来检查(缺少)重叠并拥有 2 个版本。
  • @PeterCordes 单独不会改变输出。也许我需要确保指针对齐?
  • 它可能有助于承诺编译器它们与ap = __builtin_assume_aligned(ap, 32) 或类似的对齐,但通常这不是自动矢量化与否的决定因素。不过,它会在没有 AVX 的情况下为您提供更高效的代码生成。

标签: c clang vectorization compiler-optimization sse


【解决方案1】:

使用非古老版本的 clang/LLVM。 Apple clang/LLVM 与主线 clang/LLVM 不同,但它们共享一个共同的代码库。

主线 clang3.3 和更新版本在 -O3 自动矢量化您的循环。 Clang3.4 和更新的自动矢量化它甚至在-O2

如果没有restrict,clang 确实会发出检查目标和两个源之间重叠的 asm(回退到标量),因此您将从 float *restrict s 获得更高效的 asm .

#include <stdlib.h>
void add_float_good(float *restrict s, float *restrict ap, float *restrict bp)
{
    for(size_t i=0;i<64;++i) {
       s[i] = ap[i]+bp[i];
    }
}

with clang3.4 -O3 (on the Godbolt compiler explorer) 编译成这个简单的汇编,具有最差的索引寻址模式和循环开销,但至少它是矢量化的。较新的 clang 喜欢展开,尤其是在针对最近的 Intel 进行调整时(例如 -march=skylake

# clang3.4 -O3
add_float_good:
        xor     eax, eax
.LBB0_1:                                # %vector.body
        movups  xmm0, xmmword ptr [rsi + 4*rax]
        movups  xmm1, xmmword ptr [rdx + 4*rax]
        addps   xmm1, xmm0
        movups  xmmword ptr [rdi + 4*rax], xmm1
        add     rax, 4
        cmp     rax, 64
        jne     .LBB0_1
        ret

请注意,如果没有 AVX,它不能为 addps 使用内存源操作数,因为没有编译时对齐保证。

clang8.0 -O3 -march=skylake 使用 YMM 向量完全展开,就像 gcc 具有相同的选项。

【讨论】:

    【解决方案2】:

    最好使用 Accelerate 明确说明这一点。在这种情况下,vDSP_vadd 可以解决问题。

    【讨论】:

      猜你喜欢
      • 2020-09-16
      • 2021-09-10
      • 2012-04-04
      • 2012-11-03
      • 2015-12-09
      • 2019-01-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多