Подтвердить что ты не робот

Использовать случаи для ithreads (потоки интерпретатора) в Perl и обоснование использования или не использования их?

Если вы хотите узнать, как использовать потоки интерпретатора Perl, там есть хорошая документация в perlthrtut (руководство по темам) и threads pragma manpage. Это определенно достаточно хорошо для написания простых сценариев.

Тем не менее, я нашел небольшое руководство в Интернете о том, почему и зачем разумно использовать потоки интерпретатора Perl. На самом деле, о них мало что говорят, и если люди говорят о них, довольно часто препятствовать людям использовать их.

Эти потоки, доступные, когда perl -V:useithreads равно useithreads='define'; и развязаны use threads, также называются ithreads и, возможно, более подходящими, так как они сильно отличаются от потоков, предлагаемых операционными системами Linux или Windows, или Java VM в том, что ничто не разделяется по умолчанию, и вместо этого копируется много данных, а не только стек потоков, что значительно увеличивает размер процесса. (Чтобы увидеть эффект, загрузите несколько модулей в тестовый script, затем создайте потоки в цикле, останавливающихся для нажатия клавиш каждый раз, и наблюдайте увеличение памяти в диспетчере задач или top.)

[...] каждый раз, когда вы запускаете поток, все структуры данных копируются в новый поток. И когда я говорю все, я имею в виду все. Это, например, включает пакеты, глобальные переменные, лексики в области. Все!

- Что вам нужно знать перед программированием Perl ithreads (Perlmonks 2003)

Когда вы изучаете предмет Perl ithreads, вы увидите, что люди не поощряют вас использовать их ( "крайне плохая идея" , "принципиально ошибочная" или "никогда не использовать ithreads для чего-либо" ).

В учебнике по потокам Perl подчеркивается, что "Perl Threads Different" , но он не очень беспокоится, чтобы объяснить, как они отличаются и что это означает для пользователя.

Полезным, но очень кратким объяснением того, что на самом деле существует ithreads, является из Coro man-страницы под заголовком WINDOWS PROCESS EMULATION. Автор этого модуля (Coro - единственные реальные потоки в perl) также не рекомендует использовать потоки интерпретатора Perl.

Где-то я читал, что компиляция perl с включенными потоками приведет к значительно более медленному интерпретатору.

На странице Perlmonks с 2003 года (Что вам нужно знать перед программированием Perl ithreads), в котором автор спрашивает: "Теперь вы может удивиться, почему Perl ithreads не использовал fork()? Разве это не имело бы больше смысла?" Это, похоже, написано автором прагмы forks. Не уверен, что информация, указанная на этой странице, сохраняется в 2012 году для новых Perls.

Вот некоторые рекомендации по использованию потоков в Perl, которые я перегонял из своих чтений (возможно, ошибочно):

До сих пор мое исследование. Теперь, спасибо за любой свет, который вы можете пролить на эту проблему потоков в Perl. Каковы некоторые разумные варианты использования для ithreads в Perl? В чем причина их использования или не использования?

4b9b3361

Ответ 1

Короткий ответ: они довольно тяжелые (вы не можете запустить их более дешево), и они демонстрируют неожиданное поведение (несколько смягченное последними модулями CPAN).

Вы можете безопасно использовать Perl ithreads, рассматривая их как независимых Актеров.

  • Создать поток:: Queue:: Any для "work".
  • Запустить несколько ithreads и "result" Очереди, передающие им ( "work" + собственный "результат" ) Очереди по закрытию.
  • Загрузка (требуется) всего остального кода, требуемого вашим приложением (не до потоков!)
  • При необходимости добавьте работу для потоков в очередь.

В "рабочих" ithreads:

  • Ввести любой общий код (для любой работы)
  • Блокировка - удаление очереди из очереди
  • Спросить - загрузить любые другие зависимости, необходимые для этой части работы.
  • Выполняйте работу.
  • Передайте результат обратно в основной поток через очередь результатов.
  • Вернуться к 2.

Если некоторые "рабочие" потоки начинают становиться немного мутными, и вам нужно ограничить потоки "работника" некоторым числом, а затем запускать новые на своем месте, а затем сначала создать поток "пусковой установки", задачей которого является запускать "рабочие" потоки и подключать их к основному потоку.

Каковы основные проблемы с Perl ithreads?

Они немного неудобны для "общих" данных, так как вам нужно объяснять общий доступ (не большая проблема).

Вам нужно следить за поведением объектов с помощью методов DESTROY, поскольку они выходят из области видимости в каком-то потоке (если они еще нужны в другом!)

Большая: данные/переменные, которые явно не разделены, - это CLONED в новые потоки. Это удар производительности и, возможно, совсем не то, что вы намеревались. Работа вокруг заключается в том, чтобы запустить ithreads из довольно "первозданного" состояния (не так много загруженных модулей).

IIRC, в пространстве Threads:: существуют модули, которые помогают с явным определением зависимостей и/или очисткой клонированных данных для новых потоков.

Кроме того, IIRC, есть немного другая модель, использующая ithreads, называемые потоками "квартиры", реализованные Thread:: Appartment, которая имеет другой шаблон использования и другой набор компромиссов.

Результат:

Не используйте их, если вы не знаете, что делаете: -)

Fork может быть более эффективным в Unix, но история IPC намного проще для ithreads. (Это могло быть смягчено модулями CPAN с тех пор, как я в последний раз смотрел: -)

Они еще лучше, чем потоки Python.

В Perl 6 может быть что-то гораздо лучше.

Ответ 2

Я несколько раз использовал perl-потоки. Они наиболее полезны для запуска некоторого процесса и продолжения с чем-то еще. У меня нет большого опыта в теории того, как они работают под капотом, но у меня есть много практического опыта в кодировании с ними.

Например, у меня есть поток сервера, который прослушивает входящие сетевые подключения и выдает ответ о состоянии, когда кто-то спрашивает об этом. Я создаю этот поток, затем перемещаюсь и создаю еще один поток, который контролирует систему, проверяет пять элементов, спящий несколько секунд и снова зацикливается. Для сбора данных монитора может потребоваться 3-4 секунды, затем он будет завален в общую переменную, и поток сервера может прочитать, когда это необходимо, и немедленно вернуть последний известный результат кому бы то ни было. Поток монитора, когда он обнаруживает, что элемент находится в плохом состоянии, запускает отдельный поток для восстановления этого элемента. Затем он переходит, проверяя другие предметы, пока плохой ремонтируется, и отбрасывает другие потоки для других плохих предметов или присоединяется к завершенным потокам ремонта. Основная программа все время зацикливается каждые несколько секунд, следя за тем, чтобы потоки монитора и сервера не соединялись/не выполнялись. Все это может быть написано как куча отдельных программ, использующих другую форму IPC, но потоки perl упрощают ее.

Другое место, где я их использовал, - это фрактальный генератор. Я бы разделил части изображения с помощью некоторого алгоритма, а затем запустил столько потоков, сколько у меня есть процессоры для выполнения этой работы. Каждый из них сводил их результаты в один объект GD, который не вызывал проблем, потому что каждый из них работал с разными частями массива, а затем, когда это было сделано, я выписал изображение GD. Это было мое введение в использование потоков perl и было хорошим введением, но затем я переписал его на C, и это было на два порядка быстрее:-). Затем я переписал версию Perl с потоком, чтобы использовать Inline:: C, и это было всего на 20% медленнее, чем чистая версия C. Тем не менее, в большинстве случаев, когда вы хотите использовать потоки из-за интенсивного использования процессора, вы, вероятно, захотите просто выбрать другой язык.

Как упоминалось другими, fork и threads действительно перекрываются для многих целей. Coro, однако, на самом деле не позволяет использовать многопроцессорную или параллельную обработку, например, fork и thread, вы будете видеть только ваш процесс, используя 100%. Я слишком упрощаю это, но я думаю, что самый простой способ описать Coro - это планировщик для ваших подпрограмм. Если у вас есть подпрограмма, которая блокирует вас, вы можете прыгать в другую и делать что-то еще, пока вы ждете, например, у вас есть приложение, которое вычисляет результаты и записывает их в файл. Один блок может вычислять результаты и вставлять их в канал. Когда он заканчивается, другой блок начинает записывать их на диск. Пока этот блок ждет диск, другой блок может снова начать вычислять результаты, если он получает больше работы. По общему признанию, я не много сделал с Коро; это звучит как хороший способ ускорить некоторые вещи, но меня немного отпугивает, не имея возможности сделать сразу две вещи.

Мои личные предпочтения, если я хочу многопроцессорствовать, - использовать fork, если я делаю много мелких или коротких вещей, потоков для нескольких больших или долгоживущих вещей.