Внедрение Haskell в forkIO - PullRequest
       2

Внедрение Haskell в forkIO

2 голосов
/ 14 июня 2019

Разные ОС имеют разные подсистемы параллелизма, есть процессы ОС, потоки POSIX и сегодня также потоки "LWP" в Linux, Windows имеют процессы, волокна, потоки и т. Д. Каждый процесс является планировщиком по планировщику ОС и получает собственный объем ЦП. время. Это верно для Linux "LWP", потому что они являются процессами, но разделяют пространство памяти, и это не относится к потокам пользовательского пространства, где все потоки совместно используют один квант времени ЦП.

У Haskell есть forkIO. Я нашел в источниках на Haskell следующие комментарии:

Планирование потоков на Haskell выполняется внутри Haskell. исполняемая система, и не использует ни одну из поставляемых операционных систем пакеты потоков.

также

С точки зрения производительности потоки 'forkOS' (иначе) связаны гораздо больше дороже, чем 'forkIO' (он же не связан), потому что "forkOS" поток связан с конкретным потоком ОС, тогда как поток 'forkIO' может быть запущен любым потоком ОС. Переключение контекста между forkOS нить и нить 'forkIO' во много раз дороже, чем между две темы 'forkIO'.

, который подчеркивает, что потоки, созданные с помощью forkIO, не планируются планировщиком ОС. Они, как я понимаю, могут быть свободны от обычной блокировки (с опцией -thread, конечно), но, тем не менее, в этом случае есть 3 открытых вопроса для меня:

  1. как они («потоки», созданные с помощью forkIO) совместно используют эти кванты ЦП?
  2. будут ли они гарантированно распределены по разным ядрам или, поскольку они представлены одним процессом, нет? Или это недетерминированное поведение?
  3. Прав ли я, что для предотвращения влияния помех лучше использовать forkOS, чем forkIO? Я имею в виду, если у меня 2 потока, и один из них обслуживает HTTP, а другой выполняет операции ввода-вывода с большим диском, то лучшим решением будет использование forkOS, чем forkIO?

Ответы [ 2 ]

2 голосов
/ 14 июня 2019
  1. Потоки Haskell используют совместную многопоточность.По сути, каждый раз, когда Haskell нужно выделять память, он проверяет, прошло ли достаточно времени, и если да, то переключается на следующий поток.Точный механизм немного сложнее (я думаю, что в какой-то момент он также задействовал сигналы POSIX, например, «тревога»), но это должно быть главной идеей.

  2. Система времени выполнения делает NПотоки Haskell работают поверх K-потоков.К может быть выбран пользователем.Именно ОС решает, какое ядро ​​(ядра) будет запущено в каждом потоке ОС - это всегда может быть одно и то же ядро ​​или нет.

  3. Тяжелые операции ввода-вывода не должны быть большой проблемой,Среда выполнения Haskell использует неблокирующий ввод-вывод и опрос / выборку для мультиплексирования ввода-вывода во всех потоках.Кроме того, если у вас есть два запущенных потока Haskell, и вы выделяете как минимум два потока ОС для среды выполнения, они должны выполняться в потоках ОС, которые ОС должна выделить для обоих ядер.Не стесняйтесь экспериментировать с forkIO против forkOS, чтобы увидеть, какая из них обеспечивает наилучшую производительность для вашего случая, но forkIO должен быть лучше практически во всех случаях.

0 голосов
/ 15 июня 2019

Небольшое тестирование на Windows 10 с 4-ядерным процессором показывает результаты:

module Main where

import Control.Monad
import Control.Concurrent

t1 = forever $ print "1"
t2 = forever $ print "2"

main :: IO ()
main = do
  t1id <- forkOS t1 -- I tried forkOS and forkIO
  t2id <- forkOS t2
  getLine
  putStrLn "Done"

Для forkIO и forkOS требуется опция ghc-options: -threaded для использования многопоточного исполнения. В обоих случаях я вижу только один процесс ОС, но несколько потоков. В случае forkIO число потоков равно 4, а в случае forkOS я получаю только 3. Более интересно количество переключений контекста, оно отличается от упомянутых предложений: в случае forkIO они есть ( для разных потоков): 480000 и 48 ... а в случае forkOS они равны примерно 2, 3, 16 для одного и того же периода времени. Это означает, что forkIO делает больше переключений контекста, чем forkOS ( сотни тысяч против десятков ), и суммарное время выполнения того же ценного эффекта должно быть больше, поэтому forkOS выглядит более предпочтительным в Windows box .

Как я вижу в исходном коде GHC, потоки POSIX используются под капотом.

EDIT . Тест Linux (ps -eLf):

forkOS:

UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
...        ...   ...   ... ... ...   ... ...           ... ...
xyz     7432  4865  7432  0    7 10:03 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     7432  4865  7448  0    7 10:03 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     7432  4865  7449  0    7 10:03 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     7432  4865  7450  0    7 10:03 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     7432  4865  7451 66    7 10:03 pts/0    00:00:06 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     7432  4865  7452  0    7 10:03 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     7432  4865  7453 67    7 10:03 pts/0    00:00:06 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho

forkIO:

UID        PID  PPID   LWP  C NLWP STIME TTY          TIME CMD
...        ...   ...   ... ... ...   ... ...           ... ...
xyz     8209  4865  8209  0    6 10:08 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     8209  4865  8225  0    6 10:08 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     8209  4865  8226  0    6 10:08 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     8209  4865  8227  0    6 10:08 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     8209  4865  8228 99    6 10:08 pts/0    00:00:06 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho
xyz     8209  4865  8229  0    6 10:08 pts/0    00:00:00 /home/xyz/prj/thr/.stack-work/install/x86_64-linux-tinfo6/lts-13.25/8.6.5/bin/yohoho

В Linux в forkIO случае у нас всего 6 LWP, и один из них использует процессор на 99%. В случае forkOS у нас есть 7 LWP, и 2 из них используют CPU примерно на 66%, что, на мой взгляд, выглядит лучше. Похоже, что forkOS предпочтительнее и в Linux.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...