Есть простая задача — сжимать видео в реальном времени. Сделал оптимизацию под многоядерники таким образом (это типа таймлайн)
— поступает кадр
— ищем свободный поток в нашем пуле потоков
— отдаем потоку кадр на сжатие
— смотрим, какие кадры уже сжались в других потоках, скидываем на диск
— goto 10
Видео приходится жать неслабых размеров (грубо говоря от 2000х2000 и до 1000х1000). Сильного прироста по скорости не заметил, при увеличении кол-ва используемых ядер (потоков). Профайлером прогнать сложно — специфика задачи. И вот что мне подумалось — пока уже поступивший кадр в обработке, предположим, что он весь лежит в L2 кеше (или его часть, в зависимости от размеров). И тут опа, еще один кадр — ядра начинают бороться за кеш (если он у них объединенный), а тут еще один. В результате выигрыша мы так и не получаем. Я правильно думаю?
И вот что я нарешал: не делить кадры поядерно, а разделять один кадр между ядрами, благо алгоритм сжатия позволяет это сделать. Если не брать в учет кеши и прочую ерунду, то у этих вариантов скорость должна быть равна. Но во втором случае в один момент времени идет работа над одним кадром и значит, конкуренция за кеш будет значительно меньше. То есть, это реальная возможность поднять скорость сжатия.
Здравствуйте, CyberDemon, Вы писали:
CD>И вот что я нарешал: не делить кадры поядерно, а разделять один кадр между ядрами
Нужно исходить из соотношения времени, затрачиваемого ядром на сжатие порции данных (части кадра, целого кадра, нескольких кадров), и времени, затрачиваемого ядром на конкуренцию с остальными ядрами. То есть, нужно добиваться того, чтобы ядро как можно больше времени обрабатывало свои собственные данные, и как можно меньше лезло к данным, разделяемым с другими ядрами (это и данные потока, и общие очереди/списки).
А профайлинг можно вставить и собственный, элементарно фиксируя значения TSC в нужных точках, и строя из них таблицу/график.
Здравствуйте, Евгений Музыченко, Вы писали:
ЕМ>Нужно исходить из соотношения времени, затрачиваемого ядром на сжатие порции данных (части кадра, целого кадра, нескольких кадров), и времени, затрачиваемого ядром на конкуренцию с остальными ядрами. То есть, нужно добиваться того, чтобы ядро как можно больше времени обрабатывало свои собственные данные, и как можно меньше лезло к данным, разделяемым с другими ядрами (это и данные потока, и общие очереди/списки).
Да там общих то данных практически нет.
Сейчас попробовал на простом тесте сымитировать работу первого и второго варианта. Получилось, что разницы нет никакой ВООБЩЕ
Буду думать дальше.
Еще случайно обнаружил вот какой факт:
если у процесса изменить affinity mask таким образом, чтобы кол-во задействованных ядер совпадало с кол-вом рабочих потоков, то общая производительность резко возрастает. Походу исключаются некоторые промахи кеша.
CD>если у процесса изменить affinity mask таким образом, чтобы кол-во задействованных ядер совпадало с кол-вом рабочих потоков, то общая производительность резко возрастает. Походу исключаются некоторые промахи кеша.
Вот это очень интересно. А у вас количество рабочих потоков не равно что-ли количеству ядер? И по какому принципу вы его выбираете?
Здравствуйте, CyberDemon, Вы писали:
CD>Да там общих то данных практически нет.
странное какое-то сжатие у вас. в нормальных алгоритмах сжатия видео общие данные таки есть, в результате чего, собственно говоря, и достигается приемлемая степень сжатия. жать кадры независимо один от другого — некошерно, если не сказать — кошмарно.
CD>Еще случайно обнаружил вот какой факт: CD>если у процесса изменить affinity mask таким образом, чтобы кол-во задействованных ядер совпадало с кол-вом рабочих потоков, то общая производительность резко возрастает. Походу исключаются некоторые промахи кеша.
неудивительно. вы ж закрепили за ядрами "свои" потоки. если их не закрепить, то планировщик оси перебрасывает поток на любое свободное ядро. допустим, поток A1 выполнялся на ядре C1, а поток A2 — на C2. и оба они успели скэшироваться (кэш первого уровня у всех ядер свой собственный). и тут — оба! планировщик кидает A1 на C2 или даже на C3. и привет! а если и процессоров больше одного, то это ласты полные и окончательные, т.к. у них еще и кэш второго уровня у всех свой собственный.
ЗЫ. affinity mask задает не кол-во используемых ядер, а именно закрепляет потоки за ядрами. так что сдается мне, что вы неправильно поняли назначение этой функции.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Здравствуйте, TarasCo, Вы писали:
TC>Вот это очень интересно. А у вас количество рабочих потоков не равно что-ли количеству ядер? И по какому принципу вы его выбираете?
Юзер выбирает, сколько потоков ставить (максимум — кол-во логических ядер).
Новые результаты. Если не использовать манипуляции с маской, то второй вариант таки обгоняет первый, но только при определенных условиях — если размер фрейма меньше размера L3 кеша (у моего core i5 он 8 метров), то обгон есть, если уже больше — разницы нет. Это отмечается только при условии использования всех ядер.
Ну а если пользуем не все ядра, например 2 из 4, то надо обязательно на процесс маску вешать, чтобы он юзал только 2 ядра — это дает (в моем синтетическом случае) эффект.
Например, размер кадра 1440х900 (ну у меня моник такой), 32битный цвет = ~5Mbytes. FPS видео и "алгоритм" не берем в учет.
Заводим 4 ядра и результаты такие: первый 43%, второй 58% (проценты — кол-во обработанных кадров).
Заводим 2 ядра без affinity mask: оба по 18%
Заводим 2 ядра с affinity mask 0x03: 22%, 27%
Это были запуски в студии (debug версия, но не в debug режиме).
А потом запустил из эксплорера последний вариант с двумя ядрами и немного прифигел — 34%, 49%. Смотрел TMonitor-ом частоту работы ядер — множитель (забыл как оно называется) выходит за стандартные пределы, что есть гут
После чего снова первый тест повторил с 4мя ядрами — 71%, 82%. Че-то студия мутит...
Короче, выводы я определенные сделал, сейчас попробую изменить "алгоритм" в тесте. На данный момент там тупо синус значений одного буфера пишется в другой.
Здравствуйте, CyberDemon, Вы писали:
CD>Да там общих то данных практически нет.
странное какое-то сжатие у вас. в нормальных алгоритмах сжатия видео общие данные таки есть, в результате чего, собственно говоря, и достигается приемлемая степень сжатия. жать кадры независимо один от другого — некошерно, если не сказать — кошмарно.
CD>Еще случайно обнаружил вот какой факт: CD>если у процесса изменить affinity mask таким образом, чтобы кол-во задействованных ядер совпадало с кол-вом рабочих потоков, то общая производительность резко возрастает. Походу исключаются некоторые промахи кеша.
неудивительно. вы ж закрепили за ядрами "свои" потоки. если их не закрепить, то планировщик оси перебрасывает поток на любое свободное ядро. допустим, поток A1 выполнялся на ядре C1, а поток A2 — на C2. и оба они успели скэшироваться (кэш первого уровня у всех ядер свой собственный). и тут — оба! планировщик кидает A1 на C2 или даже на C3. и привет! а если и процессоров больше одного, то это ласты полные и окончательные, т.к. у них еще и кэш второго уровня у всех свой собственный.
ЗЫ. affinity mask задает не кол-во используемых ядер, а именно закрепляет потоки за ядрами. так что сдается мне, что вы неправильно поняли назначение этой функции.
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
Здравствуйте, мыщъх, Вы писали:
М>странное какое-то сжатие у вас. в нормальных алгоритмах сжатия видео общие данные таки есть, в результате чего, собственно говоря, и достигается приемлемая степень сжатия. жать кадры независимо один от другого — некошерно, если не сказать — кошмарно.
Специфика задачи
М>неудивительно. вы ж закрепили за ядрами "свои" потоки. если их не закрепить, то планировщик оси перебрасывает поток на любое свободное ядро. допустим, поток A1 выполнялся на ядре C1, а поток A2 — на C2. и оба они успели скэшироваться (кэш первого уровня у всех ядер свой собственный). и тут — оба! планировщик кидает A1 на C2 или даже на C3. и привет! а если и процессоров больше одного, то это ласты полные и окончательные, т.к. у них еще и кэш второго уровня у всех свой собственный.
М>ЗЫ. affinity mask задает не кол-во используемых ядер, а именно закрепляет потоки за ядрами. так что сдается мне, что вы неправильно поняли назначение этой функции.
Нет, я правильно понял — просто раньше с такими вопросами никогда не сталкивался и работа планировщика задач меня полностью устраивала.
Здравствуйте, мыщъх, Вы писали:
М>ЗЫ. affinity mask задает не кол-во используемых ядер, а именно закрепляет потоки за ядрами. так что сдается мне, что вы неправильно поняли назначение этой функции.
Кстати, я же для процесса маску задавал, а не для потоков процесса.
Кибер демон. Привет. ты во многих вещах фундаментально заблуждаешься.
Во первых — озвучь плз название алгоритма сжатия.
во вторых — поделюсь опытом. я решал подобную задачу для декодирования жпег-2000. Довольно успешно.
Как то кэш ты странно считаешь. если взять, что картинка входная 1000 на 1000 — то только одна компонента видео будет занимать мегабайт. при одном байте на пиксель. В любом алгоритме сжатия выполняются преобразования минимум в точности 16 бит на пиксель — что уже увеличивает объем входных данных. Добавим остальные компоненты, добавим промежуточные буфера, которых в зависимости от реализации может потребоваться столько же памяти, сколько и для входных — и получается, что никаких существующих на данный момент размеров кэшей второго уровня не хватит, чтобы поместить в себя все данные для одной картинки.
Попробуй поиграть с размером входной картинки — и вообще расскажи задачу поподробнее — интересно же
Жако
пожалуйста не надо излишнего цитирования — модератор
Здравствуйте, jakor, Вы писали:
J>Кибер демон. Привет. ты во многих вещах фундаментально заблуждаешься. J>Во первых — озвучь плз название алгоритма сжатия.
присоединяюсь к вопросу. и в упор не понимаю, почему нельзя жать только разницу с предыдущим кадром. в реальное время это укладывалось еще во времена третьих пней, причем степь сжатия была уже сопоставима с "оффлайновыми" компрессорами. существует очень немного причин, чтобы сжимать кадры независимо друг от друга, поскольку степень сжатия при этом получается очень низкая.
J> получается, что никаких существующих на данный момент размеров J> кэшей второго уровня не хватит, чтобы поместить в себя все данные для одной картинки.
это если картинку сжимать одним блоком. а на фига это делать при таком разрешении? любые алгоритмы сжатия покажут не чуть не худший результат по степени сжатия если картинку разбить на несколько частей (например, на четыре) и сжимать их отдельно друг от друга. но это опять-таки от алгоритма и формата данных зависит...
J>Попробуй поиграть с размером входной картинки — и вообще расскажи задачу поподробнее — интересно же
кстати, настораживает то, что картинка квадратная
и еще настораживает то, куда и как складируются сжатые кадры. допустим, у нас есть четыре ядра, которые захватывают четыре соседних кадра и жмут их. допустим так же, что волею случая ядра заканчивают работу в обратном порядке, т.е. четвертый кадр сжимается раньше всех, а последним сжимается первый кадр. что делают ядра? тупо ждут окончания сжатия первого кадра?
americans fought a war for a freedom. another one to end slavery. so, what do some of them choose to do with their freedom? become slaves.
CD>Короче, выводы я определенные сделал, сейчас попробую изменить "алгоритм" в тесте. На данный момент там тупо синус значений одного буфера пишется в другой.
А заодно померь скорость обработки данных. Если она будет в районе 50МБ/c — то ты просто упираешься в скорость своего жесткого диска. Также помни, система пытается кешировать файловые данные и ты можешь на своих тестах получать результаты, отличающиеся в десятки раз. С другой стороны, если твоя прога работает с большими объемами данных, надо следить, чтобы объем выделенных буферов не приближался к размеру ОЗУ — иначе производительность может падать из-за свопинга.
Здравствуйте, jakor, Вы писали:
J>Кибер демон. Привет. ты во многих вещах фундаментально заблуждаешься.
Бывает
J>Во первых — озвучь плз название алгоритма сжатия.
Ну я парочку использую. Один — сборная солянка, по принципам похоже на HuffYUV, второй практически один-в-один MJPEG.
J>во вторых — поделюсь опытом. я решал подобную задачу для декодирования жпег-2000. Довольно успешно.
Интересно.
J>Как то кэш ты странно считаешь. если взять, что картинка входная 1000 на 1000 — то только одна компонента видео будет занимать мегабайт. при одном байте на пиксель. В любом алгоритме сжатия выполняются преобразования минимум в точности 16 бит на пиксель — что уже увеличивает объем входных данных. Добавим остальные компоненты, добавим промежуточные буфера, которых в зависимости от реализации может потребоваться столько же памяти, сколько и для входных — и получается, что никаких существующих на данный момент размеров кэшей второго уровня не хватит, чтобы поместить в себя все данные для одной картинки.
Я ошибся, когда говорил про второй уровень кеша. Третий, конечно же Второй маленький, а вот третьего более-менее хватает.
J>Попробуй поиграть с размером входной картинки — и вообще расскажи задачу поподробнее — интересно же
Задачу я уже рассказал — сжимать RGB32 uncompressed видео с максимальной скоростью с приемлемой степенью сжатия (соответственно, качество).
Здравствуйте, мыщъх, Вы писали:
М>присоединяюсь к вопросу. и в упор не понимаю, почему нельзя жать только разницу с предыдущим кадром. в реальное время это укладывалось еще во времена третьих пней, причем степь сжатия была уже сопоставима с "оффлайновыми" компрессорами. существует очень немного причин, чтобы сжимать кадры независимо друг от друга, поскольку степень сжатия при этом получается очень низкая.
Когда-то давно, когда я только выбирал подходящие по параметрам алгоритмы, я пробовал так же добавлять разницу с предыдущим кадром. На скорость сжатия повлияло в худшую сторону, потому оказался.
М>это если картинку сжимать одним блоком. а на фига это делать при таком разрешении? любые алгоритмы сжатия покажут не чуть не худший результат по степени сжатия если картинку разбить на несколько частей (например, на четыре) и сжимать их отдельно друг от друга. но это опять-таки от алгоритма и формата данных зависит...
Вот как раз я и хочу отойти от "формата" один кадр на одно ядро и перейти к один кадр на все ядра.
М>кстати, настораживает то, что картинка квадратная
Да я это для упрощения
М>и еще настораживает то, куда и как складируются сжатые кадры. допустим, у нас есть четыре ядра, которые захватывают четыре соседних кадра и жмут их. допустим так же, что волею случая ядра заканчивают работу в обратном порядке, т.е. четвертый кадр сжимается раньше всех, а последним сжимается первый кадр. что делают ядра? тупо ждут окончания сжатия первого кадра?
Сейчас сделано так — перебираются ядра, закончившие работу и их результат в порядке очередности скидывается на диск.
Да, ждут. Ситуация, когда четвертый сожмется быстрее первого ну очень маловероятна, потому я такой потерей пренебрег.
Здравствуйте, TarasCo, Вы писали:
TC>А заодно померь скорость обработки данных. Если она будет в районе 50МБ/c — то ты просто упираешься в скорость своего жесткого диска. Также помни, система пытается кешировать файловые данные и ты можешь на своих тестах получать результаты, отличающиеся в десятки раз. С другой стороны, если твоя прога работает с большими объемами данных, надо следить, чтобы объем выделенных буферов не приближался к размеру ОЗУ — иначе производительность может падать из-за свопинга.
С дисками я уже напарился В одном из вариантов сжатия в определенный момент именно в диски упирается производительность.
Привет Демон !
1 — переведи ргб32 в ив12 — и уже сразу в 2 раза получишь ускорение.
2 — мжпег устарел когда мы еще не родились. Бери х264 и жми. При той же скорости получишь сжатие на порядок (10 раз минимум) выше. и с распараллеливанием там дарк шикари нормально постарался — весь геморрой он уже порешал.
жако
пожалуйста не надо излишнего цитирования — модератор
Здравствуйте, jakor, Вы писали:
J>1 — переведи ргб32 в ив12 — и уже сразу в 2 раза получишь ускорение.
Уже в yuv420 перевожу. И далее сжатие.
J>2 — мжпег устарел когда мы еще не родились. Бери х264 и жми. При той же скорости получишь сжатие на порядок (10 раз минимум) выше. и с распараллеливанием там дарк шикари нормально постарался — весь геморрой он уже порешал.
да, на x264 я уже положил глаз + интел оптимизированные кодеки для этого имеет. Сжатие лучше, чем mpeg мне, в принципе, необязательно. Тут уже важна скорость.
Здравствуйте, мыщъх, Вы писали:
М>Здравствуйте, jakor, Вы писали:
J>>Кибер демон. Привет. ты во многих вещах фундаментально заблуждаешься. J>>Во первых — озвучь плз название алгоритма сжатия. М>присоединяюсь к вопросу. и в упор не понимаю, почему нельзя жать только разницу с предыдущим кадром. в реальное время это укладывалось еще во времена третьих пней, причем степь сжатия была уже сопоставима с "оффлайновыми" компрессорами. существует очень немного причин, чтобы сжимать кадры независимо друг от друга, поскольку степень сжатия при этом получается очень низкая.
Дофига причин, помимо озвученной автором, есть чисто административные (например в CCTV ТЗ, очень часто ставится требования отсутствия межкадрового сжатия), специфические (очень нежелательны артефакты движения) и.т.д.