Преобразование из индексов на основе источника в индексы на основе назначений

Я использую инструкции AVX2 в некотором коде C.

Команда VPERMD принимает два 8-целочисленных вектора a и idx и генерирует третий, dst, путем перестановки a на основе idx. Это кажется эквивалентным dst[i] = a[idx[i]] for i in 0..7. Я вызываю этот источник на основе, потому что перемещение индексируется на основе источника.

Однако у меня есть мои расчетные индексы в форме, основанной на адресатах. Это естественно для установки массива и эквивалентно dst[idx[i]] = a[i] for i in 0..7.

Как я могу конвертировать из исходной формы в форму на основе адреса? Пример тестового примера:

{2 1 0 5 3 4 6 7}    source-based form. 
{2 1 0 4 5 3 6 7}    destination-based equivalent

Для этого преобразования я остаюсь в ymm-регистрах, так что это означает, что решения на основе адресатов не работают. Даже если я должен был вставлять каждый отдельно, поскольку он работает только с постоянными индексами, вы не можете просто установить их.

Ответ 1

Я предполагаю, что вы неявно говорите, что не можете изменить свой код для расчета исходных индексов в первую очередь? Я не могу думать ни о чем, что вы можете сделать с x86 SIMD, кроме инструкций рассеяния AVX512, которые принимают индексы на основе dst.

Хранение памяти, инвертирование и перезагрузка вектора могут быть действительно лучшими. (Или перенос в целые регистры напрямую, а не через память, возможно, после vextracti128/packusdw, поэтому вам нужно только две 64-разрядные передачи от вектора к целочисленным regs: movq и pextrq).

Но в любом случае используйте их как индексы для хранения счетчика в массиве в памяти и перезагрузите его как вектор. Это все еще медленное и уродливое, и включает задержку с задержкой в ​​магазине. Поэтому, вероятно, стоит потратить время, чтобы изменить код, генерирующий индекс, для генерации векторов в случайном порядке.