Wie @MaratDukhan festgestellt hat, führt _mm256_shuffle_epi8
(d. H. VPSHUFB
für ymm-s) nicht die vollständige 32-Byte-Zufallswiedergabe durch. Was mich betrifft, es ist ein ziemlich schade ...
, deshalb, um es ohne AVX2 zu emulieren Sie einfach jede geteilt in zwei Hälften registrieren, permute jede Hälfte, dann zusammen kombinieren:
//AVX only
__m256i _emu_mm256_shuffle_epi8(__m256i reg, __m256i shuf) {
__m128i reg0 = _mm256_castsi256_si128(reg);
__m128i reg1 = _mm256_extractf128_si256(reg, 1);
__m128i shuf0 = _mm256_castsi256_si128(shuf);
__m128i shuf1 = _mm256_extractf128_si256(shuf, 1);
__m128i res0 = _mm_shuffle_epi8(reg0, shuf0);
__m128i res1 = _mm_shuffle_epi8(reg1, shuf1);
__m256i res = _mm256_setr_m128i(res0, res1);
return res;
}
Wenn Sie das 32-Byte-Register wirklich vollständig mischen möchten, können Sie die Vorgehensweise von this paper aus verfolgen. Mischen Sie jede Hälfte mit jeder Hälfte und mischen Sie dann die Ergebnisse zusammen.
//AVX only
__m256i _emu_mm256_shuffle32_epi8(__m256i reg, __m256i shuf) {
__m128i reg0 = _mm256_castsi256_si128(reg);
__m128i reg1 = _mm256_extractf128_si256(reg, 1);
__m128i shuf0 = _mm256_castsi256_si128(shuf);
__m128i shuf1 = _mm256_extractf128_si256(shuf, 1);
__m128i res00 = _mm_shuffle_epi8(reg0, shuf0);
__m128i res01 = _mm_shuffle_epi8(reg0, shuf1);
__m128i res10 = _mm_shuffle_epi8(reg1, shuf0);
__m128i res11 = _mm_shuffle_epi8(reg1, shuf1);
__m128i res0 = _mm_blendv_epi8(res10, res00, _mm_cmplt_epi8(shuf0, _mm_set1_epi8(16)));
__m128i res1 = _mm_blendv_epi8(res11, res01, _mm_cmplt_epi8(shuf1, _mm_set1_epi8(16)));
__m256i res = _mm256_setr_m128i(res0, res1);
return res;
}
Wenn Sie sicher sind, dass nur die untere Hälfte des reg
verwendet wird, dann können Sie Linien für reg1
entfernen, res10
, res11
, und entfernen Sie den Vergleich und die Mischung: Ohne AVX2 wäre es so ähnlich sein. In der Tat könnte es effizienter sein, mit SSE zu bleiben und 128-Bit-Register zu verwenden, wenn Sie kein AVX2 haben.
Das allgemeine 32-Byte-Shuffling signifikant mit AVX2 optimiert werden kann:
//Uses AVX2
__m256i _ext_mm256_shuffle32_epi8(__m256i reg, __m256i shuf) {
__m256i regAll0 = _mm256_permute2x128_si256(reg, reg, 0x00);
__m256i regAll1 = _mm256_permute2x128_si256(reg, reg, 0x11);
__m256i resR0 = _mm256_shuffle_epi8(regAll0, shuf);
__m256i resR1 = _mm256_shuffle_epi8(regAll1, shuf);
__m256i res = _mm256_blendv_epi8(resR1, resR0, _mm256_cmpgt_epi8(_mm256_set1_epi8(16), shuf));
return res;
}
Vorsicht: Code nicht getestet!
Wahrscheinlich haben Sie nicht bemerkt, aber AVX2 'VPSHUFB ymm, ymm, ymm/m256' ist nicht wirklich eine 256-Bit-Shuffle, sondern es ist 2x 128-Bit-Shuffle. –
Interessant. Vielen Dank! – alecco