2014-07-24 36 views
3

AVX支持浮點數據類型__m256和__m256d等按位邏輯操作。avx浮點按位邏輯運算的原因是什麼?

但是,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 

因此,我對內部表示的假設可能是錯誤的(或者我做了一些愚蠢的錯誤)。

所以問題是:有沒有一種方法可以使用浮點邏輯,並確保結果有意義的事實是安全的?

+5

在IEEE754中,-1不是0xffffffff,它是0xbf800000。 – genisage

+1

@genisage,當你與例如'_mm256_cmp_ps(x,y,1)'它返回-1 = 0xffffffff而不是0xbf800000。浮點AVX按位運算符就像整數AVX運算符一樣工作,除非它們在浮點執行uni而不是整數運算。 –

+0

可以在C++中對浮點數進行按位運算符。看到我的答案。這是一個相當不錯的假設,x86-64代碼中的所有浮點運算都將使用IEEE754。 –

回答

7

如果您'使用AVX內部函數,那麼你知道你正在使用IEEE754浮點數,因爲這就是AVX所做的。

一些位操作的彩車上有意義的

  • 選擇,如延的答案,但正如SSE4.1的,我們有blendvps及其親屬做,在一個指令
  • 絕對值(掩模遠符號)
  • 否定(XOR與等於-0.0f)
  • 轉移標誌
  • 提取指數(罕見)

它主要用於操縱符號,或者選擇性地將整個浮點數清零,而不是用於分解指數或有效位的各個位 - 可以這樣做,但它很少有用。

+0

好的答案。到目前爲止,在使用avx方面與SSE2相比,我獲得的很少,但blendvps操作無疑是使用avx的原因。 –

+0

您可以使用AVX2整數運算對浮點值執行所有這些操作。問題是爲什麼當你可以使用'mm256_and_si256'時,需要'_mm256_and_ps'。 –

+1

@Zboson也許。不過,這並不是問題所在。標題看起來像是要問這個問題,但問題的主體似乎更關心浮動的按位操作如何有意義。 – harold

2

程序員可以完全確定如何表示單精度浮點數。如何實現功能是另一回事。我已經使用了按位操作來實現符合IEEE-754的半精度浮點數。在IBM爲此提交專利之前,我還在2003年使用了拆分操作。

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 - 不適用於ARM,在此您可以執行fpsel操作)

4

原因是,在執行單元bypass-delays-when-switching-execution-unit-domainswhy-do-some-sse-mov-instructions-specify-that-they-move-floating-point-values的域之間進行切換可能存在處罰。在這種情況下,從浮點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