6

AVX 允许按位逻辑运算,例如和/或浮点数据类型 __m256 和 __m256d。

但是,C++ 合理地不允许对浮点数和双精度数进行按位运算。如果我是对的,则无法保证浮点数的内部表示,编译器是否会使用 IEEE754,因此程序员无法确定浮点数的位会是什么样子。

考虑这个例子:

#include <immintrin.h>
#include <iostream>
#include <limits>
#include <cassert>

int main() {

    float x[8] = {1,2,3,4,5,6,7,8};
    float mask[8] = {-1,0,0,-1,0,-1,0,0};
    float x_masked[8];

    assert(std::numeric_limits<float>::is_iec559);

    __m256 x_ = _mm256_load_ps(x);
    __m256 mask_ = _mm256_load_ps(mask);

    __m256 x_masked_ = _mm256_and_ps(x_,mask_);

    _mm256_store_ps(x_masked,x_masked_);

    for(int i = 0; i < 8; i++)
        std::cout << x_masked[i] << " ";

    return 0;
}

假设使用 IEEE754,因为 -1 的表示为 0xffffffff,我希望输出为

1,0,0,4,0,6,0,0

而相反

1 0 0 1.17549e-38 0 1.17549e-38 0 0

因此,我对内部表示的假设可能是错误的(或者我犯了一些愚蠢的错误)。

所以问题是:有没有一种方法可以使用浮点逻辑并且对结果有意义的事实是安全的?

4

3 回答 3

12

如果您使用的是 AVX 内在函数,那么您知道您使用的是 IEEE754 浮点数,因为这就是 AVX 所做的。

对浮点数有意义的一些按位运算是

  • 选择,就像 Jens 的回答一样,尽管从 SSE4.1 开始,我们blendvps和它的亲戚在一个指令中就可以做到这一点
  • 绝对值(屏蔽掉符号)
  • 否定(与 -0.0f 异或)
  • 转移标志
  • 提取指数(罕见)

主要是为了操纵符号,或者选择性地将整个浮点数归零,而不是为了处理指数或有效数字的各个位 - 你可以这样做,但它很少有用。

于 2014-07-24T21:17:23.167 回答
5

原因是在执行单元的域之间切换可能会受到惩罚bypass-delays-when-switching-execution-unit-domainswhy-do-some-sse-mov-instructions-specify-that-they-move-floating点值。在这种情况下,从浮点 AVX 执行单元切换到整数执行 AVX 单元。

例如,假设您想比较浮点 AVX 寄存器xy

z = _mm256_cmp_ps(x, y, 1);

AVX 寄存器z包含布尔整数值(0 或 -1),然后您可以根据需要使用_mm256_and_ps或使用逻辑与_mm256_and_si256。但_mm256_and_ps停留在同一个执行单元和_mm256_and_si256切换单元,可能会导致旁路延迟。

编辑:关于 C++ 中浮点数的位运算符,它当然是可能的,有时也很有用。这里有一些简单的例子。

union {
    float f;
    int i;
} u;
u.i ^= 0x80000000; // flip sign bit of u.f
u.i &= 0x7FFFFFFF; // set sign bit to zero //take absolute value
于 2014-07-25T07:35:35.500 回答
3

程序员可以完全确定单精度浮点是如何表示的。如何实现功能是另一回事。我利用按位运算来实现符合 IEEE-754 的半精度浮点数。早在 2003 年,我也曾使用过分支移除操作——在 IBM 为此申请专利之前。

static inline __m128 _mm_sel_ps(__m128 a, __m128 b, __m128 mask ) {
    b = _mm_and_ps( b, mask );
    a = _mm_andnot_ps( mask, a );
    return _mm_or_ps( a, b );
}

此示例演示如何使用 SSE2 删除浮点分支。使用 AVX 也可以达到同样的效果。如果您尝试(相同的技术)使用标量删除分支,由于上下文的切换,您将不会获得任何性能(适用于 x86 - 不适用于您有 fpsel 操作的 ARM)

于 2014-07-24T20:58:43.457 回答