2015-06-05 46 views
6

__m256i vektörünün öğelerini karıştırmak istiyorum. Ve böyle bir şey yapan bir intrinsik _mm256_shuffle_epi8 var, ancak bir çapraz şerit shuffle gerçekleştirmiyor.__m256i vektörünün karıştırıcı unsurları

AVX2 yönergelerini kullanarak nasıl yapabilirim?

+0

Belirli karışık veya bir çapraz şeritli 'pshufb' sahipmiş gibi herhangi shuffle? – harold

+0

SSE kodunun optimizasyonu için _mm_shuffle_epi8 kullanıyorum. Ancak AVX ve SSE talimatlarının ortak kullanımı iyi bir fikir değil, değil mi? –

+0

SSE talimatları VEX kodlu olduğu sürece iyidir. – harold

cevap

8

bu işlemi taklit bir yolu vardır, ama çok güzel değil:

const __m256i K0 = _mm256_setr_epi8(
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0); 

const __m256i K1 = _mm256_setr_epi8(
    0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 
    0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70); 

inline const __m256i Shuffle(const __m256i & value, const __m256i & shuffle) 
{ 
    return _mm256_or_si256(_mm256_shuffle_epi8(value, _mm256_add_epi8(shuffle, K0)), 
     _mm256_shuffle_epi8(_mm256_permute4x64_epi64(value, 0x4E), _mm256_add_epi8(shuffle, K1))); 
} 
+0

Güzel değil, ama benim durumumda çalışıyor. Teşekkür ederim. –

+0

Aslında bana göre çok güzel. – BeeOnRope

1

İlk - Bir açıklama - Intel olağan şartname shuffle desen de bit 0-3 tanımlanan gerektirir Her bayt için her bayt. Çapraz şerit karıştırma yapmak istediğinizde, karma deseniniz YMM kaydındaki 15'in üzerindeki konum dizininde bulunan baytları göstermek için bit 4'ü de kullanır.

Varsayımlar: karıştırmak istediğiniz şey YMM0 içinde ve desen YMM1'de.

kod aşağıdaki gibidir:

mask_pattern_0 db  0FH 
mask_pattern_1 db  10H 

vpbroadcastb ymm2,byte ptr mask_pattern_0 ; Load the mask 
vmovdqu  ymm5,ymm2 
vpsubb  ymm3,ymm2,ymm1    ; YMM3 has neg for all those exceeding 15 in original shuffle pattern 
vpsignb  ymm4,ymm1,ymm3    ; YMM4 replicates shuffle pattern with a neg at all those that are above 15 in the original shuffle pattern 
vperm2i128 ymm2,ymm0,ymm0,00010001b ; Save the upper 128 bits of the target YMM0 to YMM2 in both upper and lower 128 bits 
vperm2i128 ymm0,ymm0,ymm0,00100000b ; This replicates the lower 128 bits of YMM0 to upper 128 bits of YMM0 
vpshufb  ymm0,ymm0,ymm4    ; This places all those with index below 16 to appropriate place, and sets a zero to other bytes 
;We now process the entries in shuffle pattern with index above 15 
vpsubb  ymm3,ymm1,ymm5    ; Now all those above 15 have a positive value 
vpsignb  ymm4,ymm1,ymm3    ; YMM4 has negatives for all those below 15 in original shuffle pattern YMM1 
vpbroadcastb ymm5,byte ptr mask_pattern_1 ; Load the mask value 10H 
vpsubb  ymm4,ymm4,ymm5 
vpshufb  ymm2,ymm2,ymm4    ; Save the shuffle in YMM2 
vpaddb  ymm0,ymm0,ymm2 

Bu aynı zamanda YMM1 içerdiği desen bakir olmasını sağlar - VPSHUFB öğretim doğrudur olarak. Bu yardımcı olur

Güven ...

İlgili konular