Как мы можем поменять байт в Vector256 (System.Runtime.Intrinsics.X86)? - PullRequest
1 голос
/ 06 октября 2019

Я оптимизирую фильтр Гаусса в c #, используя новое пространство имен System.Runtime.Intrinsics.X86 (отдельная инструкция, несколько данных), найденное в .net core 3.0.

Я работаю с Vector256для большей части алгоритма, но в конце я должен сделать деление. Я нашел, как перейти от моего Vector256 к 2 Vector256, чтобы иметь возможность разделить, но у меня возникли проблемы с возвращением его в краткую версию, чтобы я мог выводить данные. Я пытаюсь использовать Avx2.PackUnsignedSaturate (vector1, vector2), который фактически дает мне Vector256, но элементы были mixte (вид порядка байтов, но есть индивидуальные значения каждого из моих ushort)

Все, что мне нужно, это поменять пару байтов посередине. Использование обычного цикла (без SIMD) для возврата значения в выводе было бы простым, но также и пустой тратой времени (ну, я думаю ... трудно сказать, если я не могу сравниться с решением simd)

-Я пробовал случайное перемешивание на Vector256 в виде байтов. Я не в состоянии достичь того, что мне нужно, кажется, движение байтов ограничено их соответствующими 128 битами. -Я пробовал смотреть на MSDN, там нет примеров или описаний этих новых функций, поэтому для большинства из них я понятия не имею, что они делают -Я пытался смотреть на руководство Intel (https://software.intel.com/sites/default/files/managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf), Хотяони действительно объясняют некоторые вещи, те, которые, я думаю, мне понадобятся (возможно, XCHG или BSWAP?), не могут найти их в пространстве имен.

var initialVector1 = System.Runtime.Intrinsics.Vector256.Create(1, 2, 3, 4, 5, 6, 7, 8);
var initialVector2 = System.Runtime.Intrinsics.Vector256.Create(9, 10, 11, 12, 13, 14, 15, 16);

var convertedBackToUshort = Avx2.PackUnsignedSaturate(initialVector1, initialVector2);

Содержимое convertBackToUshort должно быть: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16

но я получаю: 1, 2, 3,4, 9, 10, 11, 12, 5, 6, 7, 8, 13, 14, 15, 16

Используя Avx2.Shuffle(convertedBackToUshort, mask), я не могу принести 9обратно на правую сторону (несколько попыток с помощью цикла for «перебить маску» безуспешно)

1 Ответ

2 голосов
/ 06 октября 2019

Avx2.PackUnsignedSaturate aka VPACKUSWB / VPACKUSDW, как и многие 256-битные операции, работает как две 128-битные версии операции бок о бок, а не как уменьшенная версия 128-битной версии. На этой странице есть хорошее изображение . Также есть перестановки между рядами, например Avx2.Permute4x64, которые вы можете использовать для приведения блоков в их «естественный» порядок, если хотите. Это займет Vector256<UInt64>, но это не имеет значения, просто переосмыслите ваш вектор до и после.

Операции упаковки хорошо сочетаются с функциями распаковки (например, Avx2.UnpackLow), если вы используете те, а не функции«конвертируйте» функции, тогда вам не понадобятся дополнительные перестановки.

Использование скалярного цикла действительно неэффективно не только потому, что это скалярный цикл, но также и потому, что преобразование между векторами и «связкой скаляров» связано с накладными расходами. .

В этом вопросе есть более глубокая проблема, потому что фильтр Гаусса (или вообще любая свертка на самом деле) обычно не включает в себя деление и, следовательно, в конечном итоге не нуждается в этом шаге. Поскольку ваши данные являются короткими, вы можете использовать Avx2.MultiplyHigh для масштабирования с коэффициентом от 0 до 1 без необходимости делать что-либо сложное.

...