GHC中Haskell线程与OS线程之间的关系

Mar*_*ila 16 concurrency haskell ghc

我试图找出Haskell的线程(forkIO生成的线程)究竟是如何映射到OS线程的.

我找到的第一个信息来源,

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

指定所有轻量级线程实际上都在一个OS线程上运行,并且只有当Haskell线程块具有安全IO操作时,GHC运行时才会生成一个新的OS线程来运行其他Haskell线程,以便IO调用不会阻止整个计划.

第二个信息来源来自这里,

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

这清楚地表明Haskell线程以平衡的方式映射到预定义数量的预先创建的OS线程.这或多或少意味着,如果我有80个轻量级线程,并且在运行我的程序时传入选项+ RTS -N 8,那么将创建至少8个OS线程,并且每个这样的线程将运行10个轻量级线程.在具有8个CPU核心的机器上,这意味着大约10个Haskell线程/核心.

第二个信息来源似乎是更准确的一个,我希望GHC运行时在运行使用该-threaded标志编译的程序时会表现出这种确切的行为.

谁能证实这一点?而且,如果第二个版本是正确的,绑定线程的目的是什么 - 使用forkOS生成的 - 它是否仅用于处理使用线程本地数据的本机代码?

Mik*_*kov 23

编译程序时不-threaded使用单个OS线程来运行所有Haskell线程.外部调用将阻止所有正在运行的Haskell线程.

编译的程序-threaded可以使用多个OS线程并行运行多个Haskell线程(可以通过该+RTS -N选项控制OS线程的数量).标记的外部调用safe不会阻止其他正在运行的Haskell线程(因此-threaded,+RTS -N1如果您有多个Haskell线程并发出可能需要很长时间的外部调用,则使用它可能是有益的).标记的外部调用unsafe在GHC中实现为简单的内联函数调用,并将阻止调用它们的OS线程.

关于您的第一个来源,它描述了从单个功能的角度发出外国呼叫时会发生什么.甲能力被定义为一个虚拟CPU运行Haskell代码,并在螺纹RTS对应于OS线程的集合,仅其中之一是运行Haskell代码在任何时间(其他OS线程用于制作对外呼叫而不阻塞的Haskell线程).当Haskell线程进行safe外部调用时,它将被置于挂起的线程列表中,并且该功能被赋予不同的Haskell线程.

一个绑定的Haskell线程制作国外呼叫固定相关操作系统线程.一个未绑定的线程没有相关的操作系统的线程:此线程调用外资可在任何操作系统线程进行.绑定线程用于与库进行交互,对于这些库来说,对哪个调用库是从哪个OS线程(例如OpenGL)进行交互,后者将其渲染上下文存储在OS-thread-local-state中.

更多信息可以在GHC手册和以下文章中找到:

用并发扩展Haskell外部函数接口

Simon Marlow,Simon Peyton Jones和Wolfgang Thaller,Haskell'04