2015-08-09 5 views
0

Я работаю над прототипом приложения, в основном написанного на Python (2.7) для исследовательского проекта. Приложение получает видеопоток mpegts с беспроводного устройства через UDP, а затем использует openCV для обработки/анализа видеокадров. Декомпрессия mpeg выполняется в моей собственной библиотеке C, которая в основном представляет собой только связанную с Python оболочку вокруг libavcodec. Приложение представляет собой приложение Python GLUT, которое использует GLUT для рисования и базовую обработку событий.Предотвращение потери пакетов UDP в фоновом потоке при большой нагрузке процессора потока в Python

Моя проблема заключается в том, что когда мой код обработки или кода кода OpenCV взимает плату с CPU, я получаю упавшие UDP-пакеты, что приводит к повреждению видеокадров. Я знаю, что UDP является «ненадежным» протоколом, и ожидается, что отброшенные пакеты ожидаются, но, к сожалению, это то, с чем мне нужно работать.

К счастью, у меня довольно приличная машина, на которой я запускаю это (MacBookPro11,3 2.8GHz quad core i7). Моя цель - создать систему, использующую потоки и очереди, в которых потребление UDP-пакетов и декомпрессии видео будет приоритетным, так что каждый распакованный фрейм будет получен без изменений (запрет фактических сетевых ошибок). Если мой рисунок или обработка основного потока не в состоянии идти в ногу с частотой кадров видеопотока, я бы хотел удалить все распакованные фреймы, чтобы поток mpeg оставался связным. Альтернативой является отказ отдельных пакетов UDP, но это приводит к поврежденному потоку изображения, который не восстанавливается в течение некоторого периода времени, т.е. я полагаю, получение следующего I-кадра. Это та ситуация, которую я пытаюсь избежать.

Я уже создал такую ​​систему, в которой генерируется фоновый поток, который выполняет всю работу по созданию контекста декомпрессии видео и сокета UDP. Фоновая цепочка потоков бесконечно запрашивает декомпрессор для декодированных кадров, который, в свою очередь, вызывает обратный вызов по мере необходимости, который ожидает от большего количества данных из сокета (либо с помощью select, poll или blocking recv, я пробовал все три). После получения каждого нового декомпрессированного кадра фоновый поток добавляет кадры в очередь, которые потребляются в основном потоке так быстро, как могут обрабатываться. Если очередь заполнена, потому что потребитель основного потока не может идти в ногу, тогда вновь распакованный кадр просто отбрасывается и процесс продолжается.

Проблема, с которой я столкнулась, заключается в том, что даже при использовании этой системы большая нагрузка на основной поток по-прежнему вызывает удаление пакетов UDP. Это почти как если планировщик пакетов ядра, который принимает и буферизирует входящие пакеты udp, работает в моем основном потоке, который выполняет весь чертеж и обработку видеокадров (я только наполовину знаю, о чем я говорю здесь, ре. пакетный планировщик). Если я прокомментирую весь тяжелый код обработки и рисования, запущенный в основном потоке, я никогда не получаю никаких отброшенных ошибок пакетов/mpeg-декодирования.

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

Итак, мой вопрос: что я могу сделать, чтобы все мои UDP-пакеты были израсходованы и переданы в декомпрессор как можно быстрее, независимо от основной загрузки процессора?

Я попытался установить приоритет потока фонового потока на 1.0, но это не помогает. libavcodec по умолчанию порождает 9 потоков для обработки декомпрессии, но я могу опционально ограничить его 1, который я пробовал, чтобы гарантировать, что все декомпрессии происходит в одном потоке с высоким приоритетом. Глядя на мой монитор процессора, у меня есть тонны накладных расходов на моем четырехъядерном процессоре (8 с гиперпотоком, который я тоже пытался включить и выключить).

Я был бы рад сделать настройки ядра под root, если это необходимо, поскольку это всего лишь исследовательский проект, а не приложение для доставки.

Любые советы?

ТИА

+0

Итак, сколько потоков существует и как организованы очереди? –

+0

Есть два сценария, которые я пробовал: a) основной поток + один поток с высоким приоритетом для сокета и декомпрессия; b) основной поток + один поток с высоким приоритетом для сокета и декомпрессии + разрешающий декомпрессировать, чтобы порождать 9 дополнительных потоков (с некоторыми неизвестный приоритет). – hyperspasm

ответ

1

Python напрямую не поддерживает установку приоритетов потоков, но некоторые люди имели счастье, делая это с ctypes. НО, из-за того, как работает GIL, это, вероятно, не даст вам наилучших результатов.

Лучшее, что можно сделать, это, вероятно, использовать многопроцессорность для размещения потока UDP в отдельном процессе и использовать очередь для переноса видео с этого процесса на ваш основной процесс.

Чтобы избежать взаимоблокировок, вы должны начать процесс UDP перед началом любых потоков (запуск процессов после запуска запущенных запусков проблематичен, поскольку состояние потока и состояния IPC не копируется должным образом в подпроцессы), а затем, после запуска процесса UDP , вы должны lower the priority основного процесса, прежде чем начинать с него какие-либо потоки.

Here is an interesting paper, который не является прямым на месте, но дает некоторую полезную информацию о Python (3, к сожалению) и приоритетах потоков.

+0

Потрясающе! этот ответ имеет несколько отличных результатов. Я не знал о GIL, но это хорошая информация. Я видел другие приложения Python, которые порождают отдельные процессы, но не знали почему. Я буду исследовать дальше и вернуться позже, чтобы отметить это как правильно, если я могу решить свою проблему, используя эту информацию. Благодаря! – hyperspasm

+0

BTW, я использую threading2 для установки приоритетов потоков https://pypi.python.org/pypi/threading2 – hyperspasm

+0

Вы имеете в виду, что вы уже это делали, или вы делаете это сейчас? (Причина, по которой я спрашиваю, заключается в том, что обычная программа может только уменьшить ее приоритет, а не увеличивать ее, поэтому, если вы делали это раньше и не работали, возможно, поэтому.) –

 Смежные вопросы

  • Нет связанных вопросов^_^