Коммуникация между параллельными потоками

Общие принципы, проектирование, модуляризация, темплейты и шаблоны
Аватара пользователя
Eugen Graf

Activity Professionalism Silver Black
guru
guru
Сообщения: 6502
Зарегистрирован: 13 ноя 2007, 02:20
Награды: 4
Версия LabVIEW: 2009
Откуда: Saarbrücken
Контактная информация:

Коммуникация между параллельными потоками

Сообщение Eugen Graf »

Хочу рассказать как я реализую коммуникацию между параллельными потоками в моих программах. На данный момент считаю этот способ для меня самым оптимальным. Заранее предупреждаю, что здесь будут использоваться фичи появившиеся только в 8-ой версии LabVIEW.

И так я создаю новый пустой проект в какой нибудь папке, чтобы всё относящееся к этому проекту находилось в одном месте.

Создаю прибор, в который помещаю два цикла, это и будут мои параллельные процессы. Называю этот прибор либо Main.vi либо Start.vi, ну это кто как хочет. Главное знать что этот прибор является главным и первым.
Parallel_Loops.PNG
Для начала я покажу пример передачи РАЗНЫХ! данных из одного потока в другой с использованием комманд.

Самое первое это как остановить оба параллельных процесса одной кнопкой? Конечно можно использовать для данного случая локальную переменную, но это не всегда возможно, т.к. процессы могут находится и в разных подприборах. А что же с глобальной переменной? Да, её тоже можно использовать, даже если потоки-процессы находятся в разных подприборах, но а если процессы на разных компьютерах? Для этого есть так называемая Shared Variable, да но и её использование не всегда подходит, т.к. для этого нужен так называемый поллинг (engl. polling). То есть в процессе постоянно придётся "опрашивать" переменную, что я не люблю и никогда не использую в своих программах.

И так, мы хотим остановить оба потока одной кнопкой "stop". Для этого берём для нашего примера Queue типа Boolean.
BooleanQueue.PNG
Запустите этот пример в замедленном действии highlight-модус, т.е. жёлтая лампочка в меню сверху и обратите внимание на нижний поток. Он стоит, там ничего не происходит, пока не нажата кнопка стоп!!! Это говорит о том что нижний поток не требует никаких ресурсов CPU. Если бы мы использовали вместо Queue например локальную переменную, то оба процесса время от времени опрашивали бы эту самую переменную. А у нас выходит что нижний процесс ждёт изменения, без пожирания каких либо ресурсов. В программах с несколькими процессами это не критично, но а если у вас программа из 100 и более параллельных процессов, и каждый время от времени опрашивает переменную, хотя этого можно избежать.

Ещё одним из плюсов такой конструкции является то, что вы можете запросто, без каких либо изменений, разбить этот прибор на подприборы. Но об этом позже.
Аватара пользователя
Eugen Graf

Activity Professionalism Silver Black
guru
guru
Сообщения: 6502
Зарегистрирован: 13 ноя 2007, 02:20
Награды: 4
Версия LabVIEW: 2009
Откуда: Saarbrücken
Контактная информация:

Разные типы данных

Сообщение Eugen Graf »

И так мы хотели уметь не только останавливать потоки одновременно, но и передавать какие нибудь данные из одного в другой. Как же это сделать?

А для этого нам нужна Queue "неопределённого" типа, так как заранее неизвестно что мы хотим передавать из одного потока в другой. Ведь мы хотим передавать либо boolean, либо данные (например цифры или строку). Остановимся для начала на цифрах.

А что значит "неопределённый" тип данных. Я знаю как минимум три:
1. строка, т.е. string
2. variant
3. массив, например типа U8

Почему же строка является неопределённым типом? Да просто можно любой тип, а так же что немаловажно любого размера, переделать в строку, а так же наоборот из строки получить нужный (заранее известный) тип данных. Я использую в своих программах именно строку, т.к. данные переделанные в неё отображаются так же как и в памяти компъютера, не занимая при этом больше места, чем они должны занимать. Так же это более распространённый тип, используемый и в других языках программирования. Кроме того строку можно запросто отправить например через последовательный порт или TCP/IP, для удалённой коммуникации.

И так меняем тип очереди (Queue) с boolean на string.
StringQueue.PNG
StringQueue.PNG (678 байт) 23955 просмотров
Самое первое что приходит теперь в голову, как же мне отправлять два разных типа данных в очередь строкового типа?
Да, для этого конвертируем данные в строку с помощью виай Flatten To String перед их отправлением в очередь.
CaseTrue.PNG
CaseTrue.PNG (6.18 КБ) 23952 просмотра
CaseFalse.PNG
CaseFalse.PNG (6.36 КБ) 23972 просмотра
И так с верхним циклом вроде бы всё понятно, просто конвертируем какие бы то ни были данные в строку и отправляем в очередь.
А что делать в нижнем цикле? Я предлагаю конвертировать данные из строки обратно в данные используя виай Unflatten From String.

Да, но ведь тип должен быть заранее известен! Что же делать, какой тип прицепить сверху этого виай? Ведь у нас их два разных?
Type.PNG
Type.PNG (4.72 КБ) 23966 просмотров
Выход есть! О типе данных находящихся в "пакете" можно сообщать. Для этого можно просто прицепить его перед самими данными! Вот как это делается.
Type1.PNG
Type2.PNG
Всё, можно сказать, программа уже работает!
Есть несколько интересных идей как всё сделать удобнее и понятнее, но об этом в следующих уроках. :wink:
Main.vi
(17.9 КБ) 886 скачиваний
P.S.
Продолжение вы найдёте в этой теме:
/viewtopic.php?f=23&t=159
Ann
beginner
beginner
Сообщения: 16
Зарегистрирован: 03 май 2008, 18:32
Контактная информация:

Re:

Сообщение Ann »

работаю в 7 лв. восьмого пока нет. спасибо, что выложил картинки, т.к. в 7 файл не открывается. по поводу 8-го. вопрос. распространяется он почти свободно. но активировать его нужно только через инет. и , говорят, что необходимо постоянное подключение к инету для стабильной работы программы(так ли это?), что на нашем предприятии невозможно.
Аватара пользователя
Eugen Graf

Activity Professionalism Silver Black
guru
guru
Сообщения: 6502
Зарегистрирован: 13 ноя 2007, 02:20
Награды: 4
Версия LabVIEW: 2009
Откуда: Saarbrücken
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Eugen Graf »

Нет, интернет нужен только один раз для активации. Потом можно работать без интернета.
Аватара пользователя
mzu2006

Professionalism Tutorials Black
doctor
doctor
Сообщения: 2456
Зарегистрирован: 16 авг 2008, 02:12
Награды: 3
Версия LabVIEW: 7.1 10 11 12
Откуда: St-Petersburg (RU), Phila, Boston, Washington DC
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение mzu2006 »

А какая именно из фич появилась только в восьмой версии?
Аватара пользователя
Eugen Graf

Activity Professionalism Silver Black
guru
guru
Сообщения: 6502
Зарегистрирован: 13 ноя 2007, 02:20
Награды: 4
Версия LabVIEW: 2009
Откуда: Saarbrücken
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Eugen Graf »

mzu2006 писал(а):А какая именно из фич появилась только в восьмой версии?
Rest of Binary String
Аватара пользователя
Forward

Activity Tutorials Black
professional
professional
Сообщения: 337
Зарегистрирован: 03 мар 2008, 12:41
Награды: 3
Версия LabVIEW: 2010
Откуда: Кишинев
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Forward »

Не совсем разобрался. Допустим у меня 3 потока:
1) главный с ивент структурой (отвечает за лицевую панель)
2) работа с портом
3) различная обработка

В случае непрерывного чтения с порта поток 2 постоянно сливает данные через очередь потоку 3, где данные обрабатываются и отправляются в поток 1 по юзер ивет, где визуализируются. Допустим в потоке 3 у меня есть фильтр, параметры которого меняются с лицевой панели (т.е. с потока 1) по событию. Сам же поток 3 висит пока не пришел новый пакет из потока 2. Так вот как лучше в поток 3 заливать параметры обработки (фильтра), частота изменений которых очень мала?
Или же вообще как-то по другому все лучше делать?
Аватара пользователя
Eugen Graf

Activity Professionalism Silver Black
guru
guru
Сообщения: 6502
Зарегистрирован: 13 ноя 2007, 02:20
Награды: 4
Версия LabVIEW: 2009
Откуда: Saarbrücken
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Eugen Graf »

Но ведь твой третий поток может принимать команды с первого и со второго потока, или что то ему мешает? Конечно он может, почему он должен висеть и ждать пока не придёт команда со второго потока?
Аватара пользователя
Eugen Graf

Activity Professionalism Silver Black
guru
guru
Сообщения: 6502
Зарегистрирован: 13 ноя 2007, 02:20
Награды: 4
Версия LabVIEW: 2009
Откуда: Saarbrücken
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Eugen Graf »

Если ты скачал мою библиотеку Tasking, то можешь попробовать вот этот пример:
Вложения
Tasking_Example(2).vi
(36.87 КБ) 804 скачивания
Аватара пользователя
Forward

Activity Tutorials Black
professional
professional
Сообщения: 337
Зарегистрирован: 03 мар 2008, 12:41
Награды: 3
Версия LabVIEW: 2010
Откуда: Кишинев
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Forward »

Скорость работы всех потоков разная. Поток 2 "Драйвер работы с портом" работает быстрее всех. Поток 3 "Обработчик" работает медленнее драйвера, но быстрее потока 1 (самый медленный), который обновляет индикаторы.
Какой наиболее элегантный выход? Пропускать данные? Или же тормозить поток работы с портом?
Аватара пользователя
Eugen Graf

Activity Professionalism Silver Black
guru
guru
Сообщения: 6502
Зарегистрирован: 13 ноя 2007, 02:20
Награды: 4
Версия LabVIEW: 2009
Откуда: Saarbrücken
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Eugen Graf »

Тот поток что работает с драйвером отсылает данные с прибора обработчику и обработчик обрабатывает их. У них как минимум одна и та должна быть же скорость. Обработчик обязан принимать все данные из первого потока иначе очередь рано или поздно переполнится.
Что касается данных из обработчика третьему потоку, который показывает данные на ЛП. Здесь можно поступить так:
т.к. если например данные идут с частотой в 100 герц, ты не можешь их все показывать на ЛП, это понятно, потому что во-первых ничего видно не будет, числа будут просто быстро мелькать перед глазами, а во-вторых будет пожираться CPU. Здесь тебе надо решать либо ты выкидываешь данные и показываешь только некоторые из них (например каждую секунду одно значение), либо ты высчитываешь среднее математическое например из 100 данных и передаёшь уже отфильтрованные значения самособой автоматом получается что каждую секунду.
Аватара пользователя
Forward

Activity Tutorials Black
professional
professional
Сообщения: 337
Зарегистрирован: 03 мар 2008, 12:41
Награды: 3
Версия LabVIEW: 2010
Откуда: Кишинев
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Forward »

С первым потоком понятно. А по поводу того, что обработчик должен работать быстрее - это не всегда так. Как я в этому могу быть уверен? Я с USB могу получать по 30 Мбайт/сек и над всеми этими данными производится множество различных операций. В итоге обработчик все таки может работать медленнее...
Аватара пользователя
Eugen Graf

Activity Professionalism Silver Black
guru
guru
Сообщения: 6502
Зарегистрирован: 13 ноя 2007, 02:20
Награды: 4
Версия LabVIEW: 2009
Откуда: Saarbrücken
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Eugen Graf »

Он может только на короткое время работать медленнее, иначе очередь переполнится. Если нет другого выхода, то тебе придётся выкидывать некоторые данные, не передавая их обработчику. Ну или другой вариант - использовать например нотифаер. А ещё лучше обьеденить первый и второй потоки в один. То есть считал -> сразу обработал, а там уже по усмотрению - некоторые данные потоку лицевой панели, некоторые потоку лог, некоторые в друие потоки.
Аватара пользователя
Forward

Activity Tutorials Black
professional
professional
Сообщения: 337
Зарегистрирован: 03 мар 2008, 12:41
Награды: 3
Версия LabVIEW: 2010
Откуда: Кишинев
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение Forward »

Все ясно. Спасибо за советы.
Аватара пользователя
mzu2006

Professionalism Tutorials Black
doctor
doctor
Сообщения: 2456
Зарегистрирован: 16 авг 2008, 02:12
Награды: 3
Версия LabVIEW: 7.1 10 11 12
Откуда: St-Petersburg (RU), Phila, Boston, Washington DC
Контактная информация:

Re: Коммуникация между параллельными потоками

Сообщение mzu2006 »

Forward писал(а):обработчик должен работать быстрее - это не всегда так
eg писал(а):то тебе придётся выкидывать некоторые данные
или сохранять их, например на диск.
eg писал(а):использовать например нотифаер
А чем это лучше? Быстрее? И как ждать одновременно нотифайера и на очереди?
Forward писал(а):Допустим в потоке 3 у меня есть фильтр, параметры которого меняются с лицевой панели (т.е. с потока 1) по событию. Сам же поток 3 висит пока не пришел новый пакет из потока 2.
очередь на входе потока - одна. В которую пишет и 2 и первый потоки
eg писал(а):А ещё лучше обьеденить первый и второй потоки в один.
Зависит от того, какое максимальное время реакции системы задано в ТЗ. Для быстрого времени реакции скорее всего
не прокатит.

Ещё можно поиграть с приоритетами выполнения - скажем у потока 2 - макисмальный, у потока 3 чуть меньше и у потока 1
самый маленький. И разнести 1 и (2 и 3) по разным excution systems...
Ответить

Вернуться в «Модели программирования»