2016-08-31 13 views
0

Я использую инструкции 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

Это просто классическая «инверсия перестановок», 'dst [src [i]] = i' – harold

+0

Вправо. Но ваш код требует возможности устанавливать в соответствии с назначением. Поскольку я работаю в регистрах AVX2. Я не могу этого сделать. У меня есть рабочий код C, который делает это почти так же, как вы говорите, но мне нужно иметь возможность преобразовывать индексы, не имея возможности сделать перестановку на основе адресата, как вы предлагаете. – eyepatch

+0

Ваш 'a [i] = a [idx [i]] для i в 0..7' неправильно описал операцию VPERMD, поскольку он подразумевал, что изменения в' a' будут возвращаться в 'a [idx [ i]] 'для более поздних элементов. например Исходный 'a [0]' всегда будет уничтожен сразу, если только 'idx [0] = 0'. Я думаю, что ваш пример по-прежнему нормальный после моего редактирования, чтобы исправить эту ошибку (или предполагал, что поведение все время). –

ответ

2

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

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

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