2016-10-10 11 views
0

Мне любопытно, что является наиболее эффективным методом, когда я обрабатываю изображение по блоку.Эффективно обрабатывать блок обработки изображений?

В этот момент я применил некоторые техники векторизации, такие как я прочитал одну строку пикселей (8 пикселей в строке, каждая 8-битовая глубина) из блока 8x8. Но поскольку современные процессоры поддерживают 128/256-битную векторную работу, я думаю, что загрузка двух строк пикселей из блока изображения может улучшить скорость кода.

Но проблема заключается в том, что изображение (например, изображение 16x16, содержит 4 блока 8x8) в памяти непрерывно сохраняется от первого пикселя до последнего пикселя. Загрузка одной 8-пиксельной строки легко, но как я должен управлять указателем или выровнять данные изображения, чтобы я мог загружать 2 строки вместе?

Я думаю, что эта цифра может проиллюстрировать мою проблему ясно: pixels' address in a image

Таким образом, когда мы загружаем 8 пикселей (подряд) вместе, мы просто загружать данные 8 байт из исходного положения указателя на 1 инструкции. Когда мы загружаем вторую строку, мы просто добавляем 9 к указателю и загружаем вторую строку.

Итак, есть вопросы, есть ли способ, который мы могли бы загрузить эти две строки (16 пикселей) вместе с исходной позицией указателя?

Спасибо!

+1

Когда вы говорите * «нагрузка» *, вы имеете в виду чтение из файла? Или поместить в регистры процессора из ОЗУ? –

+0

Я имею в виду помещать данные в регистр CPU из ОЗУ – drinking

ответ

1

Чтобы выровнять каждую строку, вы можете заполнить конец каждой строки. Написание кода для поддержки более короткой ширины изображения, чем шаг между строками, позволяет вашему алгоритму работать с подмножеством изображения.

Кроме того, вам действительно не нужно все, чтобы выровнять SIMD, чтобы работать хорошо. Достаточно. Большинство наборов инструкций SIMD (SSE, NEON и т. Д.) Имеют команды без знака нагрузки. В зависимости от конкретной реализации может не быть большого штрафа.


Вы не загружаете две разные строки в один и тот же SIMD-вектор. Например, чтобы сделать 8x8 SAD (сумма абсолютных разностей) с использованием AVX2 VPSADBW, каждая 32-байтная загрузка получала данные из одной строки из четырех разных блоков 8x8. Но все в порядке, вы просто используете это, чтобы производить четыре результата SAD 8x8 параллельно, вместо того, чтобы тратить много времени на перетасовку, чтобы сделать один 8x8 SAD.

Например, Intel's MPSADBW tutorial показывает, как реализовать исчерпывающий поиск движения для блоков 4x4, 8x8 и 16x16, с внутренними характеристиками SS и Intel. По-видимому, фактическая инструкция MPSADBW фактически не стоит использовать на практике, хотя, поскольку она медленнее, чем PSADBW, и вы можете получить идентичные результаты быстрее с последовательным устранением исчерпывающего поиска, как используется x264 (и упоминается разработчиками x264 в this forum thread о том, SSE4 +0,1 поможет x264)

Некоторые сообщения пользователя SIMD-программирование из архива блога Dark Shikari в:. Дневник x264 Разработчик:

+0

Но даже если мы набиваем нули в конце каждой строки, я не понимаю, как загрузить две строки в блоке вместе?Я думаю, что инструкции с невыложенной загрузкой не помогают загружать строки буксировки в одну инструкцию? – drinking

+0

Вы хотите настроить код, который его компилятор представляет для вас? Или сделать тяжелую работу самостоятельно? В последнем случае преимущество не будет, если компилятор получит тот же результат, и если/когда вы перейдете на новый AVX или другую архитектуру, вам нужно снова «вручную сделать это». Все вещи #pragma часто дают компилятору достаточно для его сортировки, в зависимости от того, как он обрабатывает указатели и непрерывный доступ. – Holmz

+0

@drinking: вы загружаете одну и ту же строку из нескольких блоков и параллельно обрабатываете несколько блоков, поэтому вам не нужно это делать. См. Мой обновленный ответ. –