У меня есть выровненный массив целых чисел в памяти, содержащий индексы I0, I1, I2, I3. Моя цель - собрать их в регистр __m256i, содержащий I0, I0 + 1, I1, I1 + 1, I2, I2 + 1, I3, I3 + 1. Жесткая часть получает их в 256-битный регистр как I0, I0 , I1, I1, I2, I2, I3, I3, после чего я могу просто добавить регистр, содержащий 0, 1, 0, 1, 0, 1, 0, 1.AVX2, как эффективно загружать четыре целых числа в четные индексы с 256-битным регистром и копировать в нечетные индексы?
Я нашел встроенный _mm256_castsi128_si256, который позволяет мне загружать 4 целых числа в младшие 128 бит 256-битного регистра, но я изо всех сил стараюсь найти лучшие возможности для использования оттуда.
Любая помощь будет оценена по достоинству. Я имею доступ ко всем версиям SSE, AVX и AVX2 и хотел бы сделать это, используя только встроенные функции.
Edit:
Я думаю, что это работает, но я не насколько эффективно это ... в процессе тестирования.
// _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: Приведенный выше код не работает, потому что _mm256_unpacklo_epi32 не ведет себя так, как я думал. Приведенный выше код приведет к I0, I0 + 1, I1, I1 + 1, I0, I0 + 1, I1, I1 + 1.
Edit3: Следующий код работает, хотя с другой стороны я не уверен, что это самый эффективный:
__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);