纯Haskell代码需要线程池吗?

Nic*_*out 34 multithreading haskell

Real World Haskell,第28章,软件事务内存中,开发了并发Web链接检查器.它获取网页中的所有链接,并使用HEAD请求点击它们中的每一个,以确定链接是否处于活动状态.采用并发方法来构建该程序,并做出以下声明:

我们不能简单地为每个URL创建一个线程,因为如果(正如我们所料)大多数链接是实时的和响应的,那么可能会使我们的CPU或网络连接负担过重.相反,我们使用固定数量的工作线程,这些线程获取要从队列下载的URL.

我不完全理解为什么需要这个线程池而不是forkIO每个链接使用.AFAIK,Haskell运行时维护一个线程池并适当地调度它们,所以我没有看到CPU过载.此外,在关于Haskell邮件列表中的并发性的讨论中,我发现以下语句朝着相同的方向发展:

在Haskell中没有意义的一个范例是工作线程(因为RTS为我们做了这个); 而不是抓取一个工人,而只是forkIO.

是仅为网络部分所需的线程池,还是CPU的原因呢?

scl*_*clv 23

我想,核心问题是网络方面.如果你有每个链接10,000个链接和forkIO,那么你可能有10,000个套接字,你试图一次打开,这取决于你的操作系统配置方式,甚至可能不可能,效率低得多.

但是,事实上我们有绿色线程可以跨多个操作系统线程(理想情况下固定在各个内核上)进行"虚拟"调度,这并不意味着我们可以随意分配工作而不考虑CPU使用情况.这里的问题不在于我们不会为我们处理CPU本身的调度,而是上下文切换(甚至是绿色的)成本周期.每个线程,如果它处理不同的数据,将需要将该数据拉入cpu.如果有足够的数据,这意味着将内容拉入和退出cpu缓存.即使不存在,也意味着将事物从缓存中提取到寄存器等.

即使一个问题是平凡的并行,实际上也不是一个正确的想法,只是尽可能地将其分解并试图"一下子"完成.