API для перетасовки поддерживает только byte
и sbyte
.
//
// Summary:
// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
//
// VPSHUFB ymm, ymm, ymm/m256
//
// Parameters:
// value:
//
// mask:
public static Vector256<sbyte> Shuffle(Vector256<sbyte> value, Vector256<sbyte> mask);
//
// Summary:
// __m256i _mm256_shuffle_epi8 (__m256i a, __m256i b)
//
// VPSHUFB ymm, ymm, ymm/m256
//
// Parameters:
// value:
//
// mask:
public static Vector256<byte> Shuffle(Vector256<byte> value, Vector256<byte> mask);
Как бы вы сделали перетасовку других типов? Например, скажем, у меня есть Vector256<short>
и я хочу перемешаться с маской типа [0, 1, 7, 7, 3, 3, 2, 0]
?
Придется ли мне вместо этого делать это на уровне байтов? т.е. преобразовать приведенную выше маску в ее байтовый эквивалент?
Придется ли мне вместо этого делать это на уровне байтов? т.е. преобразовать приведенную выше маску в ее байтовый эквивалент?
Для вектора (u)short
обычно да (но это сложнее), если только вы не можете использовать AVX512 (для VPERMW
) или индексы выстроены в пары, чтобы вы могли перетасовать его как вектор (u)int
.
Для вектора (u)int
есть PermuteVar8x32
, что в любом случае более удобно.
Кстати, у Vector256.Shuffle
есть перегрузка для перетасовки вектора шорт, но, по крайней мере, в моих тестах она просто вызывает какой-то запасной метод, так что вы, вероятно, не захотите на него полагаться.
В общем, перетасовка вектора шорт с помощью AVX2 представляет собой немного большую загадку, чем просто перетасовка вектора байтов - перетасовка вектора байтов в целом сложнее, чем вызов Avx2.Shuffle
, что действительно является проблемой. Avx2.Shuffle
является частью решения, но VPSHUFB
не перемещает байты между двумя 128-битными половинами 256-битного вектора. Существуют различные решения в зависимости от того, как выглядят ваши индексы, но в целом идея состоит в том, чтобы в основном полагаться на перетасовку байтов и обработку перемещения между двумя 128-битными частями отдельно.
Например, вы можете создать 256-битный вектор, содержащий две копии нижней половины данных, другой 256-битный вектор, содержащий две копии верхней половины данных, перетасовать каждую из них, а затем смешать в зависимости от того, есть ли вам нужен байт из нижней или верхней части. В общем, с его помощью вы можете выполнить любое перетасовывание 32 байтов и построить на его основе перетасовку слов.
@Vastar да, и обычно да, если только ваши индексы не постоянны (для постоянных индексов вы также можете найти лучшую последовательность операций, которая обрабатывает эти конкретные индексы)
Создание копий — это комбинация GetLower
и GetHigher
с BroadcastVector128ToVector256
? Хотя похоже, что GetLower
и GetHigher
не сильно ускоряются.
@Vastar Permute2x128
тоже вариант
Я предполагаю, что пример, который вы привели в конце, будет довольно дорогим? дороже, чем перетасовка байтов? также вы имели в виду смешивание с BlendVariable?