Автор Тема: tcp-соединения мешают друг другу  (Прочитано 2900 раз)

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Здравствуйте!

Возникла проблема с одновременной работой tcp-соединений - если их больше
одного, они очень мешают друг другу. Есть программа-сервер, она создаёт от
одного до четырёх потоков, каждый из них принимает видеопоток от web-камеры
по tcp и выводит его на экран. От камер идёт mjpg - каждый кадр отдельным jpg,
размер 50-100 kB. Есть программа-клиент на другом компьюетере, в ней тоже
создаются потоки для получения jpg от программы-сервера и вывода на экран.
Соединение происходит по порту, номер которого определяется номером камеры.
После соединения сервер пересылает jpg клиенту.

10 кадров в секунду, сервер 4-ядерный, клиент 2-ядерный, загрузка невелика.
Программа на Qt.

Если поток один, то всё нормально - например, сервер передал 1000 jpg,
а клиент принял все или на один-два меньше, . Отладочный вывод после каждого jpg
показывает, что сколько послано, столько и принято, отображается тоже нормально.
Если же потоков два, то возникают огромные задержки на клиенте - в десятки
секунд. Приняться и обработаться успевают не все посланные jpg - например, оба
серверных потока послали 2800, а из клиентских один принял 2530, другой 1550 и
при этом огромная задержка в выводе, т.к. отображение замедленное. Всегда в
одном потоке отображение идёт со скоростью, близкой к нормальной, а тормозит
другой. Отладочный вывод показывает, что после приёма очередного jpg принято
оказалось больше байтов. В чём может быть причина?

Это порисходит на ALTLinux 6.0 сертифицированной. В Ubuntu этого явления
не было, но там была другая проблема - система не распределяла загрузку
по ядрам, всё ложилось на 1-е ядро, а в ALTLinux загрузка ядер равномерная.

Что делать и где искать причину? М.б., есть какие-то свойства tcp-протокола,
использование которых поможет от этого избавиться?
Пётр.

Оффлайн Skull

  • Глобальный модератор
  • *****
  • Сообщений: 20 159
    • Домашняя страница
Re: tcp-соединения мешают друг другу
« Ответ #1 : 04.12.2012 11:39:55 »
А что говорит автор программы? При реализации собственного протокола нужно быть готовым к плотной отладке сети.
Андрей Черепанов (cas@)

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Re: tcp-соединения мешают друг другу
« Ответ #2 : 04.12.2012 17:48:06 »
Автор непосредственно этой программы - я, в ней использована модель связи по tcp,
взятая из программы, написанной моим предшественником. В этом отношении ничего
не менялось, QTcpSocket в потоке на клиенте соединяется с QTcpServer в потоке на сервере
и сервер начинает пересылать jpg.
Пётр.

Оффлайн Skull

  • Глобальный модератор
  • *****
  • Сообщений: 20 159
    • Домашняя страница
Re: tcp-соединения мешают друг другу
« Ответ #3 : 04.12.2012 18:18:03 »
Тогда смотрите код и отладку в tcpdump.
Андрей Черепанов (cas@)

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Re: tcp-соединения мешают друг другу
« Ответ #4 : 04.12.2012 22:19:49 »
Возможно, там ещё проблемы с отведением памяти. Поток сам по себе ничего не делает,
только в методе run по команде start запускается на исполнение экземпляр класса Camera
для обработки, а после выхода из run он уничтожается. У моего предшественника он
и создавался в run и при выходе удалялся и он и сам поток. Я обнаружил, что в клиенте это
часто приводит к зависанию клиентской программы при попытке дать ей другой видеопоток
или при закрытии и даже к зависанию системы. Тогда я по возможности не стал удалять
экземпляр потока, а объект типа Camera стал создавать отдельной командой до старта
потока. Тогда клиент стал работать устойчиво, тормозных явлений в вышеописанном виде
тоже не было.

Это в Ubuntu, но когда я стал запускать сервер в ALTLinux, а клиент остался в Ubuntu,
в нём снова стали происходить сбои. Сейчас обе программы в ALTLinux.

Сегодня я для эксперимента попробовал вернуться к варианту, когда объект Camera
создаётся в методе run. Запустил клиент, когда сервер был готов отдавать ему два потока.
Тормозных явлений почти не было, на клиенте обе картинки отображались синхронно, было
только отставание на 1-2 секунды от картинки на сервере. А когда я на сервере добавил
клиенту 3-й поток, опять пошли задержки на десятки секунд, причём чем больше номер потока
на клиенте, тем больше задержка. А при отключении потоков зависла и клиентская программа
и система, в которой он была запущен, не реагировала даже на АAlt+SysRq+b.
Вот ещё здесь я задал этот вопрос.
http://linuxforum.ru/viewtopic.php?id=25423
Пётр.

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Re: tcp-соединения мешают друг другу
« Ответ #5 : 10.12.2012 23:33:29 »
Попробовал с tcpdump, вроде бы получается, что принято меньше jpg, чем послано.

Попробовал с помощью tcpdump посмотреть, что приходит на клиентскую сторону.
На ней двух-ядерный Intel 1.66GHz и Intel 945GM.

Если сервер посылает три потока jpg, в каждом 5раз/с, то программа успевает отобразить все три.
Если частота 10к/с, то при одном потоке успевает его вывести, но есть задержка
по отношению к этому же изображению в серверной программе на 1-2 секунды.
В клиентской программе каждый jpg декодируется немного больше, чем 50ms, 55-57.
jpg посылаются вместе со служебной информацией, это 12 байтов, в которых есть номер
jpg с момента, когда сервер начал их передавать.

Если посылать два потока, то, например, сервер в каждом послал 2371 jpg,, в сохранённом
выводе tcpdump 2202, программа успела обработать 2201. Примерно то же для другого
потока. При этом задержка в выводе изображения в клиентской программе по сравнению
с ним же в серверной уже 10-20 секунд. Если один поток отключить, то задержка в другом
постепенно выбирается.
Пётр.

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Re: tcp-соединения мешают друг другу
« Ответ #6 : 11.12.2012 20:05:59 »
Вообще похоже, что не хватает мощности клиентского модуля, т.к., когда сегодня
я запустил клиентскую программу на четырёх-ядерном модуле с Intel i7 2.00GHz и
тем же Intel 945GM, на котором до этого запускалась серверная,
в ней без всяких задержек отображались 4 видеопотока при 10к/с.
Но всё равно непонятно, почему двух-ядерный Intel 2x1.66GHz не успевает
выводить два потока при 10к/с, ведь на декодирование одного jpg ему
требуется менее 60ms и System Monitor показывает, что оба ядра недогружены.
Пётр.

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Re: tcp-соединения мешают друг другу
« Ответ #7 : 12.12.2012 14:28:03 »
Сегодня скомпилировал клиентскую программу с явным указанием в pro-файле thrread, mmx, sse и sse2.
Сравнил командой cmp её и предидущую, скомпилированную без явного указания mmx и sse,
они совпали в точности, но работать она стала вроде бы быстрее. Теперь на клиентском
модуле она уверенно успевает воспроизводить два потока с частотой 10к/с, а до этого
обычно не упевала. Qt по умолёанию многопоточная, pthread включается в любом случае.

На серверной программе я раньше не наблюдал заметного прироста производительности
при явном включении mmx и sse, прирост был единицы процентов, да и сейчас клиентская
программа на четырёх-ядерном модуле Intel 4x2.00GHZ отображала 4 потока при 10к/с
без явного влючения mmx и sse.
Пётр.

Оффлайн Speccyfighter

  • Мастер
  • ***
  • Сообщений: 10 259
Re: tcp-соединения мешают друг другу
« Ответ #8 : 12.12.2012 16:37:12 »
с Intel i7  ..., на котором до этого запускалась серверная,
в ней без всяких задержек отображались 4 видеопотока при 10к/с.
..., почему двух-ядерный Intel 2x1.66GHz не успевает
выводить два потока при 10к/с, ведь на декодирование
Peter_ , можете считать это вбросом или ляпом - мысли на мусор.

Многопоточность видео:
- Все пришли?
- Открыть заслонку
- Следующие

http://www.intel.com/cd/corporate/techtrends/emea/rus/platform-technology/hyper-threading/369646.htm
Т.е. 4-рехядерный Core i7 может обрабатывать 8 потоков (не видео! - см ссылку)
А двухядерный Core Duo только два. И решающее значение здесь имеет одновременное количество обрабатываемых процессором потоков, а не его частота.

Что и было включено:
с явным указанием в pro-файле thrread,

По ссылке:
Цитировать
Для повышения производительности была разработана концепция многопоточного программного обеспечения, в соответствии с которой команды распределяются по потокам, и эти потоки обрабатываются несколькими процессорами.
(cores/threads)

Pentium4 это тоже умел, а вот Core Duo[2 Duo] уже нет. С появлением Core iX ситуация снова поменялась
(При HyperThreading=yes: threads (Logical Cores) = cores * 2).
См. спецификацию на процессор на ark.intel.com
Не может ли быть проблема здесь?

Т.о., на мой взгляд, двухядерный Intel Atom с HyperThreading (Yes; Threads=4) и Core i3 (Yes; Threads=4) дадут в этой задаче фору двухяденому Core Duo/Core 2 Duo (HyperThreading=no).

Т.е. здесь у Core i7 явный выигрыш по распараллеливанию выполнения кода - 8 потоков.
« Последнее редактирование: 12.12.2012 18:05:01 от Speccyfighter »

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Re: tcp-соединения мешают друг другу
« Ответ #9 : 12.12.2012 22:05:23 »
Благодарю за подробные разъяснения. Что касается Qt-4.x, то она по умолчанию
многопоточная, i без явного указания thread. Вроде бы я это когда-то проверял.

Нагрузку распределяет по ядрам система, поэтому, если ресурсоёмких потоков не больше,
чем ядер, процессор должен справляться. На Intei Core Duo 2x1.66GHz сегодня эти два
потока иногда шли почти нормально, иногда один отставал. А когда попробовали
запустить клиентскую программу на Intel Core Duo 2x2.4GHz, то он стабильно выводил
4 потока при 10к/с. 1-е ядро было нагружалось до 92%, 2-е до 80%.
Пётр.

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Re: tcp-соединения мешают друг другу
« Ответ #10 : 13.12.2012 09:08:54 »
Ещё у Intel Core Duo 2x2.4GHz внутренний L2 - 4MB, а у Intel Core Duo 2x1.66GHz - 2MB.
Пётр.

Оффлайн yaleks

  • Мастер
  • ***
  • Сообщений: 6 242
Re: tcp-соединения мешают друг другу
« Ответ #11 : 28.12.2012 22:14:48 »
попробуйте то же самое делать не своей программой, а например vlc.

Оффлайн Peter_

  • Участник
  • *
  • Сообщений: 105
Re: tcp-соединения мешают друг другу
« Ответ #12 : 29.12.2012 20:01:53 »
В конце концов окаалось, что просто не хватает мощности процсссорного модуля
с Intel Core Duo 2x1.66GHz и L2 2MB. Иногда он успевает обрабатывать два потока с частотой 10к/с,
иногда нет. Если же клиентскую программу запустить на модуле с Intel Core Duo 4x2.00GHz, L2 4MB,
то он стабильно отобажает 4 таких потока.
Пётр.