Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Параллельная обработка
Форум на CrossPlatform.RU > Библиотеки > Qt > Qt Ввод/Вывод, Сеть. Межпроцессное взаимодействие
leonneon_89
Добрый день! Есть небольшой проект в котором я работаю с устройствами: спектр анализатор и контроллер управления.
Связь со спектром анализатором обеспечиваются при помощи usb, и есть библиотека для работы с ней. Со спектра необходимо получать данные меньше или равно 1 мс. В программе для получения с него данных, я создаю поток с высоким приоритетом в котором запрашиваю данные. Т.к. в windows я не нашел временной задержки меньше чем одной миллисекунды, то считываю данные в потоке без задержки времени, примерное время получения данных, 600-700 микросекунд. Загрузка процессора 50-60%, процессор двух-ядерный, core 2 duo c частотой 3ГГц.
Связь с контроллером устройств обеспечивается при помощи ethernet, udp протокол, пакеты шлются примерно раз в 1 мс. Мне необходимо получать эти сообщения
с равным интервалом по времени, в программе я тоже как и со спектром анализатором получаю пакеты в отдельном потоке, указав высокий приоритет. Если я работаю только с контроллером устройств, то получаю данные примерно раз в миллисекунду, а когда включаю еще и спектр анализатор, то данные с контроллера устройств получаю с неравными промежутками примерно так: 1 мс 1мс 1мс 0.5мс 0.5мс 0.5 мс 3 мс 1 мс 1мс, это только для сравнения. Вопрос как можно добиться того чтобы получать данные с контроллера устройств с одинаковым периодом времени? Контроллер устройств шлет стабильно данные раз в 1 мс, по снифферу тоже данные приходят равномерно через 1 мс, размер пакета маленький, так что все приходит. Еще вопрос, когда создаешь потоки в Qt, как узнать, к каким ядрам они принадлежат? Я так понимаю что windows потоки распределяет между ядрами планировщик задач, есть ли в Qt такое, чтобы можно было привязать потоки к определенным ядрам? Буду очень рад, если кто нибудь выскажет свои мнения по поводу сложившейся ситуации.
Iron Bug
Цитата(leonneon_89 @ 17.10.2013, 15:58) *
в windows я не нашел временной задержки меньше чем одной миллисекунды

есть Multimedia Timers.
есть библиотеки, которые работают с потоками на малых интервалах.

обычно USB-девайсы работают с callback'ами и проблем с приёмом данных не возникает.
leonneon_89
Цитата(Iron Bug @ 17.10.2013, 14:52) *
есть Multimedia Timers.
есть библиотеки, которые работают с потоками на малых интервалах.

обычно USB-девайсы работают с callback'ами и проблем с приёмом данных не возникает.

Как я понял мультимедиа таймер поддерживает мин задержку равную 1 мс, по крайней мере у меня на машине, а как насчет библиотек, которые работают с потоками на малых интервалах, можете сказать их названия?
Так с usb проблем и нет, данные получаю с периодом равным 0.6-0.7 мс, просто хотел мин. задержку сделать в потоке, задержка меньше чем 1 мс, чтобы процессор не так сильно нагружать.
Вся проблема с приемом данных через сокет(т.е. приема с контроллера устройств), когда одновременно программа принимает данные с контроллера устройств и со спектра анализатора.
Влад
Тут имхо проблема даже не в таймерах или мультимедиа таймерах, а в том, что Windows не является системой реального времени по определению. И даже повышение приоритетов потоков не дает никаких гарантий в отношении временных интервалов. Потому что в любой непредсказуемый момент времени шедулер Винды может отдать управление ядру системы - а процессы и потоки ядра имеют приоритет заведомо выше, чем любые пользовательские (об этом механизме подробно написано у мэтра Рихтера). И сколько там будет "шуршать диском" ядро - известно только Б.Г-у. и шедулеру системы.....

Если тебе нужно жестко выдерживать миллисекундные интервалы, есть смысл посмотреть в сторону ОСРВ - например, QNX Neutrino. Ну или подумать над изменением алгоритмов обработки данных - так, чтобы не требовалась такая уж жесткая синхронность...

И какая у тебя архитектура приложения? Мне кажется, есть смысл вынести все общение с анализатором и общение с эзернетом в два отдельных потока.
Да, в Вин можно "привязать" поток к определенному (ядру) процессора - гугли по лексеме Processor Affinity (в .NET это свойство Process.ProcessorAffinity, но есть аналог и в чисто нативном коде).
leonneon_89
Цитата(Влад @ 17.10.2013, 17:17) *
Если тебе нужно жестко выдерживать миллисекундные интервалы, есть смысл посмотреть в сторону ОСРВ - например, QNX Neutrino. Ну или подумать над изменением алгоритмов обработки данных - так, чтобы не требовалась такая уж жесткая синхронность...

И какая у тебя архитектура приложения? Мне кажется, есть смысл вынести все общение с анализатором и общение с эзернетом в два отдельных потока.
Да, в Вин можно "привязать" поток к определенному (ядру) процессора - гугли по лексеме Processor Affinity (в .NET это свойство Process.ProcessorAffinity, но есть аналог и в чисто нативном коде).

У меня так и сделано, сделал два потока с высокими приоритетами, в одном из них запрашиваю и получаю данные со спектра анализатора, в другом
принимаю udp пакеты с контроллера устройств, да у меня возникла мысль, а что если взять четырех ядерный или двух ядерный процессоры с поддержкой гипертрейдинга, и потоки вынести с наивысшим приоритетом, в различные ядра привязав их к ним, ведь по идее для нужд системы останутся другие ядра, и им не зачем обращаться обращаться к "моим работающим ядрам" или все дело обстоит иначе?

По заданию просто нужно сделать это на Windows, просто на каждое полученное сообщение от контроллера устройств необходимо получать актуальные(новые) данные со спектра анализатора.
Iron Bug
да, Windows не является системой реального времени. но можно и в ней извратиться и сделать всё довольно быстро. у меня в этом богатый опыт :)
из библиотек - во-первых, boost::thread. я как раз вот недавно собирала его и выложила пример сборки буста с наносекундными таймерами. ICU для скорости не нужна, нужен только флаг BOOST_DATE_TIME_POSIX_TIME_STD_CONFIG.
сразу скажу, под вендой наносекунды - нереально. реальный интервал, на который можно рассчитывать - микросекунда. и то если машина мощная и не особо загруженная. но это всё равно большой плюс. иногда удаётся вытянуть сотни наносекунд, порядка 200-300. под линюксом спокойно вытягивает 10-20 нс, например.
есть ещё boost::chrono. я про него немного писала тут, но я с ним много не работала, ибо он был ещё сыроват.
ещё можно делать самодельные таймеры на основе счётчика тиков. тут была тема на этот счёт, я там тоже приводила пример реализации такого таймера под вендой и линюксом.
всё зависит от того, какие нужно решать задачи. таймер сам по себе ещё мало: потому что кроме таймера есть синхронизация потоков или какие-то события, которые дёргают обработчики. а сами эти события тоже отнимают время и иногда получается, что проблема не в таймере, а в том, как быстро обработать сигнал от него.
я проводила множество тестов, поняла, что самое быстрое - это boost::thread и прерывание потока(interrupt) по таймеру. но я эти тесты проводила несколько лет назад. может, сейчас новые библиотеки стали лучше. например, стоит протестировать boost::chrono.

P.S. на самом деле, под вендой также реализованы системы RTX (Real-Time Extension), которые позволяют загружать и выполнять часть приложения в kernel mode. обычно это довольно серьёзные коммерческие продукты.

и всё-таки, я не понимаю, как от USB девайса нет callback'а. чипов USB не так много и все они реализуют более-менее одинаковую логику: инициализация, отправка данных и вызов callback'а по приходу данных. я много лет работаю в автоматизации и других реализаций ни разу не видела. может, просто есть пробемы с пониманием принципов работы с устройством? зачем там поллинг - как-то не очень понятно. разве что девайс какой-то ну слишком нестандартный. но никто таких не делает. какой чип у USB-драйвера?

и ещё: тема не относится к Qt и её надо бы перенести куда-то либо в общие вопросы, либо в раздел С++.
leonneon_89
Цитата(Iron Bug @ 17.10.2013, 21:30) *
и всё-таки, я не понимаю, как от USB девайса нет callback'а. чипов USB не так много и все они реализуют более-менее одинаковую логику: инициализация, отправка данных и вызов callback'а по приходу данных. я много лет работаю в автоматизации и других реализаций ни разу не видела. может, просто есть пробемы с пониманием принципов работы с устройством? зачем там поллинг - как-то не очень понятно. разве что девайс какой-то ну слишком нестандартный. но никто таких не делает. какой чип у USB-драйвера?

Со спектром анализатором поставляется библиотека для взаимодействия с ней и библиотека для работы с usb, мне предоставляется только заголовочный файл, в котором описаны функции для взаимодействия со спектром, это типо инициализация устройства, запрос данных, ожидание ответа и т.д. Драйвер usb предоставляется так же ими, так что я просто использую функции. Под поллингом я понимаю задержку, она никак не влияет на прием данных, просто думал, что если сделать задержку, то процессор будет меньше нагружаться.
Cпасибо на счет буста, буду пробовать.
Iron Bug
Цитата(leonneon_89 @ 18.10.2013, 12:42) *
Под поллингом я понимаю задержку, она никак не влияет на прием данных, просто думал, что если сделать задержку, то процессор будет меньше нагружаться.

поллинг - это периодический активный опрос. и он всегда плох, потому что при любом раскладе неоправданно жрёт проц.
обычно в электронике используется другая схема: девайс принимает данные и инициирует вызов софта. софт спит, пока его не вызовут через callback.
а при отправке данных обычно драйвер предоставляет overlapped event, на котором потом вызывается WaitForSingleObject (если речь идёт о венде). так что тоже никакого поллинга не требуется в принципе.

никто не делает свои USB-чипы, все пользуются стандартными. причём эти чипы по пальцам пересчитать можно и драйверы под них уже есть, и библиотеки приёма данных. нормальные, с callback'ами и event'ами. поэтому эти вопросы и вызывают у меня подозрения. у меня тут этих USB-девайсов просто море было. и все они реализованы более-менее одинаково. и библиотеки к ним имеют похожие интерфейсы. никто не изобретает велосипеды.
может, стоит всё-таки уточнить технологию по работе с библиотеками? потому что реализация получения данных через поллинг состояния - это как-то слишком неправильно.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Форум IP.Board © 2001-2024 IPS, Inc.