2016-05-26 4 views
2

Wie kann ich einen Wert von 1 auf alle Bits in einem __m256-Wert setzen? Verwenden von AVX oder AVX2-Intrinsics?Schnellste Möglichkeit, __m256-Wert auf alle EINS-Bits zu setzen

Um nur Nullen zu erhalten, können Sie _mm256_setzero_si256() verwenden.

Um alle zu bekommen, verwende ich derzeit _mm256_set1_epi64x(-1), aber ich vermute, dass dies langsamer ist als die All-Zero-Fall. Gibt es hier Speicherzugriff oder Salar/SSE/AVX-Umschaltung?

Und ich kann nicht scheinen, eine einfache bitweise NOT-Operation in AVX zu finden? Wenn das verfügbar wäre, könnte ich einfach den Setzer verwenden, gefolgt von einem Vektor NICHT.

+2

In früheren Zeiten verwendeten die Leute 'pcmpeqd xmm0, xmm0' dafür, vermutlich gibt es eine äquivalente Operation in AVX {2}? – njuffa

+4

@njuffa 'vpcmpeqd' in AVX2. Clang scheint die '_mm256_set1_epi64x (-1);' zu optimieren, das gleiche wie '_mm256_cmpeq_epi64 (_mm256_setzero_si256(), _mm256_setzero_si256());' –

+4

Siehe auch: http://stackoverflow.com/q/35085059/555045 – harold

Antwort

5

Siehe auch Set all bits in CPU register to 1 efficiently, die AVX, AVX2 und AVX512 zmm und k (Masken) Register umfasst.


Sie haben offensichtlich nicht einmal an der asm Ausgang schauen, was zu tun ist trivial:

#include <immintrin.h> 
__m256i all_ones(void) { return _mm256_set1_epi64x(-1); } 

compiles to

vpcmpeqd  ymm0, ymm0, ymm0 
    ret 

mit gcc6.1 und clang3.8.


Die erste Version von gcc zur Unterstützung von avx2 wusste genug, um diese Optimierung zu tun. Mit -mavx -mno-avx2 lädt gcc einen Vektor von Einsen aus dem Speicher. Clang erstellt ein 128bit All-Ones und verwendet vinsertf128.


Wie der Vektor-Abschnitt von Agner Fog's optimizing assembly guide beschrieben, billig ist diese Art und Weise Konstanten on the fly zu generieren. Es benötigt immer noch eine Vektorausführungseinheit, um die Einsen zu erzeugen (unlike _mm_setzero), aber es ist besser als jede mögliche Zwei-Befehlsfolge und normalerweise besser als eine Last. Siehe auch das Tag-Wiki.

Compiler mögen nicht generate more complex constants on the fly, auch solche, die von all-one mit einer einfachen Verschiebung erzeugt werden könnten. Selbst wenn Sie es versuchen, indem Sie __m128i float_signbit_mask = _mm_srli_epi32(_mm_set1_epi16(-1), 1) schreiben, führen Compiler typischerweise eine konstante Propagierung durch und setzen den Vektor in den Speicher. Dies ermöglicht es ihnen, sie in einen Speicheroperanden zu falten, wenn sie später in Fällen verwendet werden, in denen es keine Schleife gibt, die die Konstante ausheben kann.


Und ich kann nicht scheinen, eine einfache bitweise NOT-Operation in AVX zu finden?

Sie tun das durch XORing mit All-Einsen.

Verwandte Themen