alexPec 3 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба Всем доброго дня! Ищутся мысли по поводу оптимальной реализации поворота картинки. Что сделано: Поворот картинки через CORDIC. Производится поворот координаты каждого пикселя (по конвейеру) на заданный угол, вычисляется адрес пикселя в читаемой (не повернутой) картинке, прочитанные пиксели выводятся последовательно в формате ITU656. Что не устраивает: При повороте пиксели из исходной картинки читаются не через burst transfer, а по одному, т.к. при повороте получаем чтение не по последовательным, а по произвольным адресам. Поэтому шина ДДР сильно просаживается по производительности. Мало того что пиксели читаются по разным адресам, так еще из 32битного прочитанного слова мне надо только один пиксель, т.е. 8бит. Даже если не сразу выводить картинку, а скидывать в память повернутую, а потом выводить - ничего не меняется, т.к. если читаем по последовательным адресам, тогда записывать повернутую картинку придется по произвольным, так же по одному пикселю. Может кто-то как-то решал подобные проблемы неэффективного использования ДДР шины? Реализация поворота полностью аппаратная. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_4afc_ 25 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба При повороте края обрезаются или картинка уменьшается и добавляются чёрные поля? В одном случае считываемых точек больше - в другом записываемых... И потом в ПЛИС обычно множественный доступ по чтению (например к кешу) будет быстрее множественного доступа по записи (нужен мультиплексор). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
KeisN13 10 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба ставьте статику и qdr'ы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexPec 3 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба 55 минут назад, _4afc_ сказал: При повороте края обрезаются или картинка уменьшается и добавляются чёрные поля? В одном случае считываемых точек больше - в другом записываемых... И потом в ПЛИС обычно множественный доступ по чтению (например к кешу) будет быстрее множественного доступа по записи (нужен мультиплексор). Картинка при повороте вырезается из картинки бОльшего размера, поэтому ни черных полей, ни масштабирования нет. Поэтому сколько читаем точек, столько и пишем. В моем случае (сейчас) производится только рандомное чтение - дальше считанные данные отправляются сразу в ITU интерфейс, в память уже не попадают. Аппаратное чтение происходит без участия кэша (cyclone5 или zynq7000), да и весь кадр в кэш наверно не влезет. Аппаратный доступ к кэшу ЕМНИП, начинается только у ultrascale+. Да и читающий мастер написан для чтения без участия кэша. Хотя я сомневаюсь, что будет сильно лучше, т.к. процессор во время поворота свое молотит, тоже приличные объемы данных ворочает, там весь кэш думаю будет забит. Нов случае с процессором кэш здорово вывозит. Да, со статикой вариант конечно, решает проблему, но это отдельный корпус, дополнительные габариты и куча занятых ног... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 25 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба 2 hours ago, alexPec said: Даже если не сразу выводить картинку, а скидывать в память повернутую, а потом выводить - ничего не меняется, т.к. если читаем по последовательным адресам, тогда записывать повернутую картинку придется по произвольным, так же по одному пикселю. Можно сделать внутри FPGA буфер на восемь строк и сохранять во внешней памяти уже повернутые пиксели burst'ами по восемь пикселей за одно обращение к памяти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 73 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба поворот на произвольный угол +-180гр? а то если углы ограничены небольшими градусами может можно обойтись внутренним буфером на несколько строк? и наоборот читать подряд, писать "под углом", но в буфер всего на несколько строк, и выдавать из него строку по заполнении. ну или даже всё оставить как есть, но сделать промежуточный буфер на несколько строк соответствующих максимальному углу поворота, а не на всю картинку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexPec 3 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба Только что, blackfin сказал: Можно сделать внутри FPGA буфер на восемь строк и сохранять во внешней памяти уже повернутые пиксели burst'ами по восемь пикселей за одно обращение к памяти. Не понял как это. Например, берем (условно, для простоты квадратный экран 500х500) пиксели № (0,0), (1,0),(2,0),(3,0). Их читаем бастом. Поворачиваем их на 90 градусов - они оказываются на позициях (0,499), (0,498), (0,497), (0,496) - это все НЕ последовательные адреса. На 45 градусов, например, повернуть - вообще где попало в памяти после поворота окажутся. 4 минуты назад, _pv сказал: поворот на произвольный угол +-180гр? а то если углы ограничены небольшими градусами может можно обойтись внутренним буфером на несколько строк? и наоборот читать подряд, писать "под углом", но в буфер всего на несколько строк, и выдавать из него строку по заполнении. ну или даже всё оставить как есть, но сделать промежуточный буфер на несколько строк соответствующих максимальному углу поворота, а не на всю картинку. Вообще хотелось бы +/- 90 градусов, но даже 30 градусов (меньше даже заморачиваться не стоит) было бы не плохо. Но даже при 30 строка даже в 640 пикс. при повороте займет tg(30)*640 = 369 пикс. по вертикали. Т.е. почти весь кадр 640*480. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 25 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба 18 minutes ago, alexPec said: Не понял как это. Берем квадратный экран 500х500. Читаем burst'ом во внутреннюю SRAM FPGA из внешней DDR пиксели: 1-ая строка: (0,0), (0,1),(0,2),(0,3),...,(0,499); 2-ая строка: (1,0), (1,1),(1,2),(1,3),...,(1,499); 3-я строка: (2,0), (2,1),(2,2),(2,3),...,(2,499); ... 8-ая строка: (7,0), (7,1),(7,2),(7,3),...,(7,499). Пишем burst'ом по 8 beats во внешнюю DDR из внутренней SRAM пиксели: 1-ый столбец: (0,0), (1,0),(2,0),(3,0),...,(7,0); 2-ой столбец: (0,1), (1,1),(2,1),(3,1),...,(7,1); ... 459-ый столбец: (0,459), (1,459),(2,459),(3,459),...,(7,459). Повторяем эту операцию для всех 500 строк. Читаем burst'ом из внешней DDR полученные пиксели по строкам и выводим их во внешний порт.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_pv 73 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба 12 minutes ago, alexPec said: Не понял как это. Например, берем (условно, для простоты квадратный экран 500х500) пиксели № (0,0), (1,0),(2,0),(3,0). Их читаем бастом. Поворачиваем их на 90 градусов - они оказываются на позициях (0,499), (0,498), (0,497), (0,496) - это все НЕ последовательные адреса. На 45 градусов, например, повернуть - вообще где попало в памяти после поворота окажутся. внутреннему буферу на 8 строк при записи наплевать что адреса оказались непоследовательными, а вот прочитали-то вы их бурстом 8 штук последовательно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexPec 3 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба Да, туплю что-то. Согласен. Надо только аппаратно высчитать начало и конец баста ( в смысле адреса). Ну и еще наложится логика маскирования начала записываемого участка и конца, т.к. начало и конец часто не будут совпадать с границами записываемого слова. Но в части оптимизации обращения к ДДР выглядит сильно лучше. Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_4afc_ 25 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба При любом угле - можно уйти от рандомности так: 1 переводим картинку в полярную систему координат с минимальным нужным шагом угла 2 переводим картинку из полярной системы координат начиная с нужного угла. PS: Если исходная картинка статичная - в памяти достаточно иметь результат 1 действия и совершать над ним только второе... Я так спрайт на экране делал в виде кораблика который поворачивался на тот градус куда корабль повёрнут... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alexPec 3 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба 6 часов назад, _4afc_ сказал: При любом угле - можно уйти от рандомности так: 1 переводим картинку в полярную систему координат с минимальным нужным шагом угла 2 переводим картинку из полярной системы координат начиная с нужного угла. PS: Если исходная картинка статичная - в памяти достаточно иметь результат 1 действия и совершать над ним только второе... Я так спрайт на экране делал в виде кораблика который поворачивался на тот градус куда корабль повёрнут... не совсем понял мысль. Картинка с матрицы (с камеры) идет в построчно. В память ее лучше всего ложить тоже построчно - бастами. Непонятно как перевод в полярную систему позволит решить проблему рандомного обращения к памяти. Даже если мы ее переведем (запишем по порядку, так сказать, "лучи" из центра экрана к периферии с разными углами), то сама запись в таком формате - это то же рандомные обращения к памяти. Весь кадр меняется каждые 20 мс. Ну а если картинка статичная - то можно и один раз преобразовать, потратить время на рандомную запись. Хотя натолкнули меня на мысль сделать предвычисления по началам/концам бастов и маскам при дискретных углах и забивать их в таблицу, которой будет пользоваться "вращалка". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_4afc_ 25 18 сентября, 2019 Опубликовано 18 сентября, 2019 · Жалоба 1 hour ago, alexPec said: не совсем понял мысль. Картинка с матрицы (с камеры) идет в построчно. В память ее лучше всего ложить тоже построчно - бастами. Непонятно как перевод в полярную систему позволит решить проблему рандомного обращения к памяти. Даже если мы ее переведем (запишем по порядку, так сказать, "лучи" из центра экрана к периферии с разными углами), то сама запись в таком формате - это то же рандомные обращения к памяти. Весь кадр меняется каждые 20 мс. Ну а если картинка статичная - то можно и один раз преобразовать, потратить время на рандомную запись. Я хотел сказать, что при таком подходе (через полярное преобразование) уходит зависимость от угла в вычислениях, хоть и требуются 2 этапа. А раз так - проще их оптимизировать по отдельности, по вычислениям. У меня нет опыта решения в лоб вашей задачи, да ещё под ДМА и БУРСТ. Здесь уже ваш опыт... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
lexx 0 19 сентября, 2019 Опубликовано 19 сентября, 2019 · Жалоба С точки зрения памяти запись наиболее проблемное место. Посмотрите в описании сколько максимально (размер слова) читается/пишется за один запрос памяти, это будет ширина буфера, далее читайте вниз по памяти до заполнения квадрата и потом обратно в память. P.S. расположение картинки может быть как 1D, линейное, так и 2D. По сути также линейное, но размер по ширине ограничивается размером страйда. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
blackfin 25 19 сентября, 2019 Опубликовано 19 сентября, 2019 · Жалоба 33 minutes ago, lexx said: С точки зрения памяти запись наиболее проблемное место. С чего это вдруг? Вот диаграммы чтения и записи burst'ами по 8 слов типовой DDR3 памяти Micron'а: Никаких особых проблем ни на чтении, ни на записи не видно.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться