Russian Qt Forum

Qt => Многопоточное программирование, процессы => Тема начата: Igors от Июль 14, 2017, 15:05



Название: Жмем FPS
Отправлено: Igors от Июль 14, 2017, 15:05
Добрый день

Есть файл где записаны картинки "кадр за кадром", формат свой, читалка тоже своя. Имею всего 12 fps - а надо хотя бы 30. Ну ладно, попробовал поставить побольше кеш чтения, а потом и вовсе QBuffer, Результат "в минус" что меня удивило, читалке уже больше 20 лет.

Ну что, выходит надо читать кадры параллельно (а как еще ускориться?). Как это лучше организовать?

Спасибо


Название: Re: Жмем FPS
Отправлено: qate от Июль 14, 2017, 21:19
>а как еще ускориться?

проц побыстрее


Название: Re: Жмем FPS
Отправлено: Racheengel от Июль 15, 2017, 00:30
"параллельное" чтение тут не поможет - это один и тот же файл (физически).
надо сначала понять - проблема в железе или в алгоритме чтения? где bottleneck?
если коду 20 с плюсом лет, то может тупо помочь перекомпиляция его с включенным SSE/AVX.


Название: Re: Жмем FPS
Отправлено: Igors от Июль 15, 2017, 06:36
Философия люмпена "как бы не работать" была описана еще в рассказах Максима Горького, отвечать на нее нет смысла.  Остается разве что это
надо сначала понять - проблема в железе или в алгоритме чтения? где bottleneck?
Профайлер показывает что все теряется на "обвязках". В принципе там обычный run-length encoding. Тупо читается счетчик, если старший бит взведен - читаются точки имеджа одна за одной. Каждое чтение - обращение к файлу. Число таких чтений огромно, поэтому хотя у файла и стоит кеш 64К, но пока до него доберемся, да перевернем ендиану, да то-се - вот время и ушло. Оптимизировать это может и возможно, но это кропотливая ручная работа на недели (одних под-форматов штук 5)   


Название: Re: Жмем FPS
Отправлено: Racheengel от Июль 15, 2017, 11:55
Читать каждую точку непосредственно из файла - это, конечно, да...
Думается мне, что если файл прочитать целиком в память и только потом декодировать - одно это решит все проблемы.


Название: Re: Жмем FPS
Отправлено: Igors от Июль 15, 2017, 12:59
Читать каждую точку непосредственно из файла - это, конечно, да...
Думается мне, что если файл прочитать целиком в память и только потом декодировать - одно это решит все проблемы.
Файл может занимать много гектар (кадров много), поэтому разумнее кешировать читаемый кадр - но об этом я уже писал в стартовом посте.

Неужели "разпоточить" чтение кадров так сложно что надо чего-то ловчить, хитрить, изворачиваться? Может проще сделать?  :)

Ну а клянчить у юзверя проц помощнее - вообще позор  :)


Название: Re: Жмем FPS
Отправлено: Racheengel от Июль 15, 2017, 15:05
Неужели "разпоточить" чтение кадров так сложно что надо чего-то ловчить, хитрить, изворачиваться? Может проще сделать?  :)

Ну а как Вы себе представляете это самое "разпоточить"?
Есть один огромный файл, где какой кадр физически (с каким смещением) - неизвестно, так я понимаю.
Самое быстрое в этом случае будет читать большим куском в память (по мегабайту, допустим) и разжимать.
RLE такая вещь, что тоже трудно ее распараллелить. Ну разве что у Вас есть какие-то специальные сигнатуры начала каждого кадра?


Название: Re: Жмем FPS
Отправлено: Igors от Июль 15, 2017, 15:17
Ну а как Вы себе представляете это самое "разпоточить"?
Есть один огромный файл, где какой кадр физически (с каким смещением) - неизвестно, так я понимаю.
Самое быстрое в этом случае будет читать большим куском в память (по мегабайту, допустим) и разжимать.
RLE такая вещь, что тоже трудно ее распараллелить. Ну разве что у Вас есть какие-то специальные сигнатуры начала каждого кадра?
Ну ессно достать кадр по индексу/времени можно
Цитировать
--- Заголовок файла ---
 - число кадров, (суб)формат. тыры-пыры
--- Кадр 1 -----
Header
  - опции, палитра и др лабуда
  - длина упакованных данных
Data
   - упаковнные данные
--- Кадр 2 -----
...
--- Кадр 3 -----
...


Название: Re: Жмем FPS
Отправлено: Racheengel от Июль 15, 2017, 20:07
как вариант:
- 1 поток читает кадр целиком в память
- передает его второму потоку - воркеру, который занимается разжиманием
- параллельно 1 поток читает 2й кадр, передает следующему свободному воркеру и т.д.


Название: Re: Жмем FPS
Отправлено: Igors от Июль 16, 2017, 09:14
как вариант:
- 1 поток читает кадр целиком в память
- передает его второму потоку - воркеру, который занимается разжиманием
- параллельно 1 поток читает 2й кадр, передает следующему свободному воркеру и т.д.
Ну разделить чтение-распаковку - уже нужно приложить усилия, а зачем? Мы можем создать N "читающих" дав каждому свой кадр. Да, все они полезут в один файл, но за счет кешей чтения вряд ли будет серьезный оверхед. Ну первым делом я это и проверил. Получил... "наоборот", т.е. при чтении неск нитками разных кусков файл.. читается заметно быстрее  :)  Понятно что расклад зависит от ОС и кол-ва свободной памяти.

Ну то ладно, а вот что с пресловутой "архитектурой"? Ясно что считанный кадр нужно где-то хранить пока не придет время его показа. В общем все сводится к классической задаче "производитель-потребитель", производитель не должен вырываться вперед, кол-во произведенных должно быть ограничено. Когда потребитель "потребляет" - он должен толкнуть производителя (место освободилось).

Ладно, будем изучать классику  :)


Название: Re: Жмем FPS
Отправлено: Igors от Июль 17, 2017, 09:07
Все сделал, на 4 нитках получил даже под 60 fps, хотя конечно рез-т зависит от кеша винта, изменить это я не могу. А интересная задачка! Производитель загружает нужный кадр и помещает его "на склад" (в контейнер). Там кадр хранится пока потребитель его не заберет. Загрузка нового кадра начинается если

- есть свободный производитель
- есть место на складе

Примерные структурки (псевдокод)
Код
C++ (Qt)
struct CJob {
 QImage mImage;        // кадр
 int mFrameIndex;        // индекс кадра
 int mNumRef;             // сколько раз потребитель затребовал имедж (0 = слот свободен)
 CWorker * mWorker;   // worker загружающий имедж (0 = имедж готов)
};
 
QVector<CJob> mJobs;  // "склад"
 
class CWorker : public QThread {
...
 CJob * mJob;             // загружаемый кадр (0 = worker свободен)
};
 
QVector<CWorker *> mWorkers;  // бригада worker'ов
 
Увы, это вряд ли кому-то интересно. Вот если бы "где чего достать"  :'(


Название: Re: Жмем FPS
Отправлено: Old от Июль 17, 2017, 09:24
Увы, это вряд ли кому-то интересно. Вот если бы "где чего достать"  :'(
Конечно не интересно, в данном виде это одноразовая поделка, что-бы заткнуть дыру в вашем коде.
Я много лет назад вам уже писал, что все, кому это надо, давно написали себе удобные и универсальные пулы ниток с очередью, которая умеет их эффективно нагружать.
На форуме есть как минимум две темы, где я описывал как сделать очередь задач и как ее использовать совместно с пулом потоков.


Название: Re: Жмем FPS
Отправлено: Авварон от Июль 17, 2017, 12:16
Old
А кинь в меня ссылочкой, плз.


Название: Re: Жмем FPS
Отправлено: Old от Июль 17, 2017, 12:20
Old
А кинь в меня ссылочкой, плз.
Вот уже отбирал темы: http://www.prog.org.ru/index.php?topic=29975.msg228236#msg228236


Название: Re: Жмем FPS
Отправлено: Igors от Июль 17, 2017, 13:37
Цитировать
Кто мне писал на службу жалобы? Не ты? Да я же их читал!


Название: Re: Жмем FPS
Отправлено: kuzulis от Июль 23, 2017, 15:48
А если перенести все декодирование в GPU вместо CPU? Есть такой вариант? (просто подумалось)...


Название: Re: Жмем FPS
Отправлено: Igors от Июль 24, 2017, 08:25
А если перенести все декодирование в GPU вместо CPU? Есть такой вариант? (просто подумалось)...
Посторонний вопрос но интересный. Какой-то разговор может быть начиная с OpenGL 4.0 или выше, до этого таких понятий как "куча" и "выделение памяти" там просто нет. Можно создать только какое-то мизерное число переменных передающихся в шейдер. Ну и в принципе GPU (рендер) работает примерно так

- есть точка (x. y) - скажите цвет в этой точке

Да, это работает с огромной скоростью (на то и бабульки снимались за карту), но увы - нельзя задать те (x, y) что хотелось, можно только "те что дали". В общем GPU реализация если и возможна, то несравненно сложнее простенького распараллеливания