repstosw 18 16 июля, 2018 Опубликовано 16 июля, 2018 (изменено) · Жалоба Бьюсь над реализацией графического фильтра HQ2X на STM32H743 (Cortex-M7). Фильтр работает, но притормаживает, когда в кадре много мелких деталей. Была предпринята оптимизация: Switch/Case из 256 значений был заменён на JumpTable. Не помогло. Исходный код фильтра (Keil ARM MDK): HQ2x.rar Требуется растянуть кадр в 2 раза по обеим осям. Есть другие фильтры Scale2x, SaI2x , LQ2x - с ними проблем нет, на STM32H743 они идут довольно шустро(написанные на C, без Asm-а). Вот тут чувак заточил под NEON и DSP фильтр HQnX (что не годится для Cortex-M7): https://pyra-handheld.com/boards/threads/ru...sp.69047/page-5 Существуют ли аналогичные графические фильтры (в частности HQ 2x), оптимизированные на ассемблере для ядер ARM Cortex-M7? Работа фильтра пояснена на рисунке: Изменено 16 июля, 2018 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 16 июля, 2018 Опубликовано 16 июля, 2018 (изменено) · Жалоба А попорбовать вместо ассемблерных вставок (которые обычно сбивают оптимизатор) использовть встроенные инлайны компилятора? В случае GCC, к примеру, могут оптимизатором варьироваться регистры, содержащие исходные значения/результаты... Кстати, сравнение для четырех восьмибитных чисел должно быть тоже в SIMD... скорее всего. Вы его делаете "в ручную". Searching for 'SSUB8'... C:\USER\SVN\CMSIS_5-5.3.0\CMSIS\Core\Include\cmsis_armcc.h(803):#define __SSUB8 __ssub8 C:\USER\SVN\CMSIS_5-5.3.0\CMSIS\Core\Include\cmsis_armclang.h(1381):__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) C:\USER\SVN\CMSIS_5-5.3.0\CMSIS\Core\Include\cmsis_armclang.h(1385): __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); C:\USER\SVN\CMSIS_5-5.3.0\CMSIS\Core\Include\cmsis_gcc.h(1590):__STATIC_FORCEINLINE uint32_t __SSUB8(uint32_t op1, uint32_t op2) C:\USER\SVN\CMSIS_5-5.3.0\CMSIS\Core\Include\cmsis_gcc.h(1594): __ASM volatile ("ssub8 %0, %1, %2" : "=r" (result) : "r" (op1), "r" (op2) ); C:\USER\SVN\CMSIS_5-5.3.0\CMSIS\Core\Include\cmsis_iccarm.h(397): #define __SSUB8 __iar_builtin_SSUB8 C:\USER\SVN\CMSIS_5-5.3.0\CMSIS\Core_A\Include\cmsis_iccarm.h(310): #define __SSUB8 __iar_builtin_SSUB8 7 occurrence(s) have been found. И самый главный вопрос - DATA CACHE включен в процессоре? Изменено 16 июля, 2018 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба Рисунок врет. Например, глаза лягушонка он размыл (округлил), а такой же черный квадрат недалеко оставил, как есть. И диагональные линии выглядят слишком красиво. Растянуть в 2 раза - половина пикселей (по одной оси) уже есть, а половину всунуть кубической интерполяцией. Еще есть пиксели по диагонали, те нужно интерполировать побеим осям. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
aaarrr 69 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба Рисунок врет. Например, глаза лягушонка он размыл (округлил), а такой же черный квадрат недалеко оставил, как есть. И диагональные линии выглядят слишком красиво. Просто это не совсем фильтр в привычном понимании. Алгоритм. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба А попорбовать вместо ассемблерных вставок (которые обычно сбивают оптимизатор) использовть встроенные инлайны компилятора? В случае GCC, к примеру, могут оптимизатором варьироваться регистры, содержащие исходные значения/результаты... Кстати, сравнение для четырех восьмибитных чисел должно быть тоже в SIMD... скорее всего. Вы его делаете "в ручную". Наскоряк не нашёл CMSIS-овский хедер, поэтому на ассемблере написал. Попробуем использовать инлайны. И самый главный вопрос - DATA CACHE включен в процессоре? Да. Без него всё очень сильно медленно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 16 июля, 2018 Опубликовано 16 июля, 2018 (изменено) · Жалоба CMSIS обычно подключен через соответствующий процессорный header - например, в моем случае: через stm32h7xx.h включен stm32h743xx.h - а в нем в районе 240 строки core_cm7.h: #define __CM7_REV 0x0100U /*!< Cortex-M7 revision r1p0 */ #define __MPU_PRESENT 1 /*!< CM7 provides an MPU */ #define __NVIC_PRIO_BITS 4 /*!< CM7 uses 4 Bits for the Priority Levels */ #define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */ #define __FPU_PRESENT 1 /*!< FPU present */ #define __ICACHE_PRESENT 1 /*!< CM7 instruction cache present */ #define __DCACHE_PRESENT 1 /*!< CM7 data cache present */ #include "core_cm7.h" /*!< Cortex-M7 processor and core peripherals */ Изменено 16 июля, 2018 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба Просто это не совсем фильтр в привычном понимании. Алгоритм. Неужели глаза размером в пиксель отличает от просто кубика? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 16 июля, 2018 Опубликовано 16 июля, 2018 (изменено) · Жалоба Рисунок врет. Например, глаза лягушонка он размыл (округлил), а такой же черный квадрат недалеко оставил, как есть. И диагональные линии выглядят слишком красиво. Растянуть в 2 раза - половина пикселей (по одной оси) уже есть, а половину всунуть кубической интерполяцией. Еще есть пиксели по диагонали, те нужно интерполировать побеим осям. Не врёт. Это волшебный фильтр. Не просто билинейная-бикубическая фильтрация , а смарт-фильтр, заточенный под пиксель-арт. В доказательство прикрепляю программу (под винду) вместе с исходником и мейкфайлом. Фильтр LQ2x (практически результат схож с HQ2x, но быстрее и легче для STM32): LQ2x_WIN32.rar Входные данные: файл test.raw, 160x102 пикселя RGB 8:8:8 Выходные данные после отработки программы : LQ2x.raw 204x320 пикселей RGB 8:8:8 В программе фильтр делает ещё поворот на 90 градусов и работает в цветовом пространстве RGB 5:6:5 (для моих целей). RAW смотреть к примеру IrfanView, выставив длину, ширину и пиксель-формат. Ну и ниже картинка с результатами фильтров (с википедии): Изменено 16 июля, 2018 пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 199 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба Была предпринята оптимизация: Switch/Case из 256 значений был заменён на JumpTable. Не помогло. Исходный код фильтра (Keil ARM MDK): Уже писали много раз и тут в том числе: все эти рукопашные inline - мёртвому припарки. При включённой оптимизации компилятор сам заинлайнит что нужно. И тем более - какие-то таблицы переходов: компилятор сам прекрасно умеет их делать если switch/case удовлетворяет некоторым условиям: достаточно большое число case и последовательное расположение case-значений. Прежде чем пытаться что-то делать в подобном духе, надо хотя-бы листинг при полной оптимизации посмотреть и подумать. А ускорить тут можно только ассемблером. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба Уже писали много раз и тут в том числе: все эти рукопашные inline - мёртвому припарки. При включённой оптимизации компилятор сам заинлайнит что нужно. И тем более - какие-то таблицы переходов: компилятор сам прекрасно умеет их делать если switch/case удовлетворяет некоторым условиям: достаточно большое число case и последовательное расположение case-значений. Прежде чем пытаться что-то делать в подобном духе, надо хотя-бы листинг при полной оптимизации посмотреть и подумать. А ускорить тут можно только ассемблером. При -O3 -Otime switch/case заменяется на Jumptable при условии, что есть некая упорядоченность в проверяемых значениях. А в фильтре она идёт в разнобой. Максимум на что можно надеяться при таком подходе - это на поиск с бинарным разделением Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 199 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба При -O3 -Otime switch/case заменяется на Jumptable при условии, что есть некая упорядоченность в проверяемых значениях. А в фильтре она идёт в разнобой. Максимум на что можно надеяться при таком подходе - это на поиск с бинарным разделением Ещё и не факт что подобная раскрутка циклов: if ((w1 != w5) && (Diff(y, RGBtoYUV[w1]))) pattern |= (1 << 0); if ((w2 != w5) && (Diff(y, RGBtoYUV[w2]))) pattern |= (1 << 1); if ((w3 != w5) && (Diff(y, RGBtoYUV[w3]))) pattern |= (1 << 2); if ((w4 != w5) && (Diff(y, RGBtoYUV[w4]))) pattern |= (1 << 3); if ((w6 != w5) && (Diff(y, RGBtoYUV[w6]))) pattern |= (1 << 4); if ((w7 != w5) && (Diff(y, RGBtoYUV[w7]))) pattern |= (1 << 5); if ((w8 != w5) && (Diff(y, RGBtoYUV[w8]))) pattern |= (1 << 6); if ((w9 != w5) && (Diff(y, RGBtoYUV[w9]))) pattern |= (1 << 7); даст ускорение. Тело цикла достаточно большое, чтобы одна команда перехода в конце незначительно влияла на скорость. Зато кеша надо намного меньше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AVI-crak 0 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба Вот тут чувак заточил под NEON и DSP фильтр HQnX (что не годится для Cortex-M7) NEON имеет множество пробелов по сравнению с возможностями Cortex-M7. И уж точно Cortex-M7 может выполнять всё что есть в NEON. Нужно просто перелопатить код, удаляя и заменяя вставки NEON функций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
GenaSPB 11 16 июля, 2018 Опубликовано 16 июля, 2018 (изменено) · Жалоба Там тоже ассемблер с "неоном". Неон умеет по 16 байт за один раз обсчитывать, Cortex-M7 только по четыре. лично я делал FIR фильтры (многоканальные, для float) с импользованием NEON. Получилось. ps: "там" это тут http://electronix.ru/redirect.php?https://...sp.69047/page-5 Изменено 16 июля, 2018 пользователем Genadi Zawidowski Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 199 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба Я так понимаю - Вы сами пытались оптимизировать функцию Diff() asm-вставками? И в её начале - закомментаренное си-тело? Если так, то действие: int c1v = (c1 & Vmask) - (c2 & Vmask); if (Absolute(c1v) > trV) совсем не аналогично варианту на асме ниже. Подумайте, что будет если к примеру c1==0x81, c2==0 в первом и во втором случае. Если конечно в реализации изначально не заложено какое-то ограничение по количеству цветов (диапазону значений байтов). Но в любом случае: взятие модуля от числа - не аналогично операции x=-x. Да и вычитать SSUB8 c1,c2 чтобы потом находить NEG от каждого байта - это как-то бессмысленно. Почему бы тогда сразу не сделать SSUB8 c2,c1 ? PS: Так что похоже у Вас ещё и реализация кривая.... :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KnightIgor 2 16 июля, 2018 Опубликовано 16 июля, 2018 · Жалоба Не врёт. Это волшебный фильтр. Не просто билинейная-бикубическая фильтрация , а смарт-фильтр, заточенный под пиксель-арт. Фильтр LQ2x (практически результат схож с HQ2x, но быстрее и легче для STM32): ОТ: Back to 80's? Не в смысле фильтров, а моды на 8-битные игры? Интересно узнать, каков back ground изысканий... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться