Связь между потоками Haskell и потоками ОС в GHC - программирование
Подтвердить что ты не робот

Связь между потоками Haskell и потоками ОС в GHC

Я попытался выяснить, как именно потоки Haskell (те, которые порождаются forkIO), сопоставлены с потоками ОС.

Первый источник информации, который я нашел,

http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Concurrent.html#g:11

указывает, что все легкие потоки фактически выполняются в одном потоке ОС и только тогда, когда потоки Haskell блокируются с безопасной операцией ввода-вывода, среда выполнения GHC порождает новый поток ОС для запуска других потоков Haskell, так что вызов IO не " t заблокировать всю программу.

Второй источник информации приходит отсюда,

http://www.haskell.org/ghc/docs/7.0.1/html/users_guide/using-smp.html

в котором четко указано, что потоки Haskell сопоставляются с предопределенным количеством заранее созданных потоков ОС сбалансированным образом. Это означает более или менее то, что если у меня будет 80 легких потоков, и я прошел бы в опции + RTS -N 8 при запуске моей программы, тогда будет создано не менее 8 потоков ОС, и каждый такой поток будет запускать 10 легких потоков. На машине с 8 ядрами процессора, что будет означать примерно 10 потоков/ядра Haskell.

Второй источник информации кажется более точным, и именно это поведение, которое я желаю, чтобы среда выполнения GHC проявлялась при запуске программы, скомпилированной с флагом -threaded.

Может ли кто-нибудь подтвердить это? А также, если вторая версия является правильной, какова цель связанного потока - тот, который создается с помощью forkOS - это только для обработки собственных код, который использует локальные данные потока?

4b9b3361

Ответ 1

Программы, скомпилированные без -threaded, используют один поток ОС для запуска всех потоков Haskell. Внешние вызовы блокируют все запущенные потоки Haskell.

Программы, скомпилированные с помощью -threaded, могут использовать несколько потоков ОС для одновременного запуска нескольких потоков Haskell (количество потоков ОС может управляться опцией +RTS -N). Зарубежные вызовы, отмеченные safe, не будут блокировать другие запущенные потоки Haskell (поэтому может быть полезно использовать -threaded даже с +RTS -N1, если у вас есть несколько потоков Haskell и вызывать внешние вызовы, которые могут занять много времени). Внешние вызовы, отмеченные unsafe, реализованы как простые вызовы встроенных функций в GHC и блокируют вызванный ими поток ОС.

Что касается вашего первого источника, в нем описывается, что происходит, когда внешний вызов выдается с точки зрения одной возможности. A возможность определяется как виртуальный процессор для запуска кода Haskell, а в потоковом RTS соответствует коллекции потоков ОС, только одна из которых запущена Haskell в любое время (другие потоки ОС используются для создания внешних вызовов без блокировки потоков Haskell). Когда поток Haskell создает внешний вызов safe, он помещается в список приостановленных потоков и возможность предоставляется другому потоку Haskell.

Связанный поток Haskell имеет фиксированный связанный поток ОС для выполнения внешних вызовов. У несвязанного потока нет связанного потока ОС: внешние вызовы из этого потока могут быть сделаны в любом потоке ОС. Связанные потоки используются для взаимодействия с библиотеками, для которых важно, какие вызовы в библиотеку сделаны из потока ОС, такого как OpenGL, который сохраняет свой контекст рендеринга в локальном состоянии OS-thread.

Дополнительную информацию можно найти в руководстве GHC и в следующей статье:

Расширение интерфейса внешних функций Haskell с помощью Concurrency

Симон Марлоу, Саймон Пейтон Джонс и Вольфганг Таллер, Хаскелл'04