Ho una matrice allineata di numeri interi nella memoria che contiene gli indici I0, I1, I2, I3. Il mio obiettivo è di inserirli in un registro __m256i contenente I0, I0 + 1, I1, I1 + 1, I2, I2 + 1, I3, I3 + 1. La parte difficile è farli entrare nel registro a 256 bit come I0, I0 , I1, I1, I2, I2, I3, I3, dopo di che posso semplicemente aggiungere un registro contenente 0, 1, 0, 1, 0, 1, 0, 1.AVX2, Come caricare in modo efficiente quattro numeri interi agli indici pari di un registro a 256 bit e copia in indici dispari?
Ho trovato l'intrinseco, _mm256_castsi128_si256, che mi permette di caricare i 4 numeri interi nei 128 bit inferiori del registro a 256 bit, ma sto cercando di trovare i migliori elementi intrinseci da utilizzare da lì.
Qualsiasi aiuto sarebbe apprezzato. Ho accesso a tutte le versioni SSE, AVX e AVX2 e vorrei farlo usando solo intrinsics.
Edit:
Credo che questo funziona, ma io non sono come efficiente è ... in fase di testarlo.
// _mm128_load_si128: Loads 4 integer values into a temporary 128bit register.
// _mm256_broadcastsi128_si256: Copies 4 integer values in the 128 bit register to the low and high 128 bits of the 256 bit register.
__m256i tmpStuff = _mm256_broadcastsi128_si256 ((_mm_load_si128((__m128i*) indicesArray)));
// _mm256_unpacklo_epi32: Interleaves the integer values of source0 and source1.
__m256i indices = _mm256_unpacklo_epi32(tmpStuff, tmpStuff);
__m256i regToAdd = _mm256_set_epi32 (0, 1, 0, 1, 0, 1, 0, 1);
indices = _mm256_add_epi32(indices, regToAdd);
Edit2: Il codice di cui sopra non funziona perché _mm256_unpacklo_epi32 non si comporta il modo in cui ho pensato. Il codice sopra darà come risultato I0, I0 + 1, I1, I1 + 1, I0, I0 + 1, I1, I1 + 1.
Edit3: Il seguente codice funziona, anche se ancora non sono sicuro se è il più efficiente:
__m256i tmpStuff = _mm256_castsi128_si256(_mm_loadu_si128((__m128i*) indicesArray));
__m256i mask = _mm256_set_epi32 (3, 3, 2, 2, 1, 1, 0, 0);
__m256i indices= _mm256_permutevar8x32_epi32(tmpStuff, mask);
__m256i regToAdd = _mm256_set_epi32 (1, 0, 1, 0, 1, 0, 1, 0); // Set in reverse order.
indices= _mm256_add_epi32(indices, regToAdd);