小编Sea*_*hin的帖子

为什么我们在 x86 上将 64 位无符号整数转换为 32 位浮点数时要设置最低有效位?

#include <cstddef>
float cast(size_t sz){return sz;}
Run Code Online (Sandbox Code Playgroud)

在 Clang 13.0.1 上编译上述代码会-mavx2 -O3生成以下代码:

cast(unsigned long):                               # @cast(unsigned long)
        test    rdi, rdi
        js      .LBB0_1
        vcvtsi2ss       xmm0, xmm0, rdi
        ret
.LBB0_1:
        mov     rax, rdi
        shr     rax
        and     edi, 1
        or      rdi, rax
        vcvtsi2ss       xmm0, xmm0, rdi
        vaddss  xmm0, xmm0, xmm0
        ret
Run Code Online (Sandbox Code Playgroud)

GCC、MSVC 和 Intel 编译器以及旧版本也可以生成类似的代码。

我理解该算法的总体目标是解决以下事实:在 AVX-512 之前,没有从 64 位无符号 int 到 float 或 double 的转换指令。

因此,如果数字大到足以被解释为负数,则会将其减半、转换,然后将其加倍。但是,如果在原始整数中设置最低有效位,那么设置它的目的是什么?

这似乎是浪费时间,因为浮点数只有 23 个有效位,并且该位保证不重要。也许如果它是增量指令,则在某些情况下可能会影响有效位。但仅仅一个 or 指令似乎没有做任何事情。

c++ assembly x86-64 clang floating-point-conversion

8
推荐指数
1
解决办法
288
查看次数

为什么不能在 std::span 上对这个循环进行 clang 矢量化,将结果写入 std::array ?

为什么 clang 17.0.1 不会矢量化以下函数中的循环:

void adapt(std::span<const F, N + 1> signal)
{
    F true_val = signal.back();
    F y = dot_prod<F, N>(&signal[0], w.begin());
    F e = true_val - y;
    F dot = dot_prod<F, N>(&signal[0], &signal[0]);
    F nu = mu / (eps + dot);
    for (size_t i = 0; i < N; i++)
    {
        w[i] += nu * e * signal[i];
    }
}
Run Code Online (Sandbox Code Playgroud)

不存在浮点关联性的附带依赖性或问题,并且 GCC 13.2 对其进行矢量化没有任何问题。

这是编译器资源管理器上完整代码的链接。

其背景是我正在尝试优化我的代码以使用矢量化点积。std::inner_product由于浮点关联性问题,通常会发出标量实现,除非您使用-ffast-math. 但是,我只想-ffast-math应用于单个函数,并且我一直在寻找一种可移植的方法来为 clang 和 GCC 执行此操作。在查看输出时,我注意到 clang 不会矢量化另一个循环。 …

c++ simd vectorization clang auto-vectorization

4
推荐指数
1
解决办法
175
查看次数