Каков наилучший способ использования SIMD/ассемблера для вычитания 2 uint16 с абсолютным значением (максимальная разница) и добавления (+ =) результата к поплавке?SIMD pixel-contrast: сумма различий между пикселем и его соседями (компоненты цвета uint16_t, суммы с плавающей запятой)?
Подобно этому примеру C'ish
c0 += fabs((float)a0 - (float)b0); // C is Float accumulator, a+b pixels
, где а и Ь беззнаковое 16-битные слова, и с представляет собой поплавок. Только одно слово -> преобразование с плавающей точкой, а не 3.
Приложение Thee обрабатывает необработанные 16-разрядные данные без знака в виде как можно большего количества RGB-пикселей.
Возможно использование AVX2/SSE4.2 на Skylake Xeon E3-1275 v5?
5 минут ограничение комментариев ?? Не удается сохранить или переименовать ???
Вы уверены, что вам нужно поплавать? Uint16 не может накапливать более 1 вычитания. Я хочу сделать подсчет окрестности, поэтому мне нужно суммировать как минимум 8 различий. В окрестности с глубиной D имеются (2D + 1)^2-1 соседи. Я также хочу иметь возможность разделить разницу, в которой uint32 может быть слишком маленьким. Я думаю, что поплавки выглядят более гладкими.
Вот немного больше фона на то, что уже работает, и как я хочу, чтобы улучшить его.
Чтобы уточнить, мой текущий код C вычисляет разницу между каналами между фиксированным домашним пикселем и 8 или более соседями. Он имеет структуру с 5 глубокими вложенными циклами: Y-строки, тогда X-cols для каждого пикселя на изображении (36 миллионов) Каналы, R. G & B - loop3 Петли 4 и 5 для строк и столбцов окрестности.
для каждого HOME пикселя ясно, что R, G и B аккумуляторов для каждого соседа,
добавить абса (home_red - nabr_red) до red_float_accumulator же для зеленых и синих копии накопленных значений в основную память
Следующим шагом было перемещение каналов на уровень 5 и все 3 вычитания, R, G и B одновременно с SIMD. Имея 48 бит/пиксель и 128 бит, доступных в каждом регистре MMX, 2 можно сделать сразу, а не только 1.
С 512-битными регистрами в AVX2 на Skylake Xeon, 10 может быть выполнено. Я ищу хорошую стратегию, чтобы сбалансировать сложность с производительностью и узнать больше об этих векторных операциях.
Мне нужны аккумуляторы R, G и B для каждого «домашнего» пикселя. Затем переместите RGB в «плавающее изображение» с тем же разрешением XY, что и uint16/channel RAW, RGB-файл. Сделайте то же сравнение контрастности для каждого пикселя.
Вы уверены, что вам нужно плавать? Сохранение всего в фиксированной точке 16b позволило бы обрабатывать вдвое большее количество элементов (но более высокая точность для промежуточных значений часто бывает полезной, поэтому не проблема). Возможна 32-битная фиксированная точка. Это может быть не очень полезно, потому что некоторые из инструкций SSE с многоступенчатыми сложными операциями (например, умножением и затем сдвигом вправо с округлением) предназначены для работы с данными 8 бит на компонент. –
Не могли бы вы переписать пример «C'ish» в цикле с соответствующими массивами? То, что вы написали, неоднозначно в отношении того, является ли 'c0' аккумулятором для всех значений (с учетом оператора' + = ') или getter является членом массива, и вам нужен diff на пиксель ... –
Хороший вопрос, это SAD расчет? Я предполагал, что нет. (и ответ почти завершен). –