当前位置: 首页 > 知识库问答 >
问题:

对于task.factory.startnew和parallel.invoke,线程可以在不同的处理器或内核上运行

卫成和
2023-03-14

我希望澄清我对.NET多线程的理解,特别是.NET方法创建的线程可能在多处理器/核系统中的不同处理器或核上同时执行。

在.NET TPL框架中,可以使用Parallel.Invoke或Task.Factory.StartNew方法来实现某种并行性。

我的理解是,在这两种情况下.NET都创建了新任务(在后台为Parallel.Invoke),然后.NET环境将这些任务分配给后台的托管线程,这些线程再分配给线程,CPU可以根据工作负载将这些线程分配给不同的内核或处理器。这两种方法的主要区别在于语义--Parallel.Invoke执行多个任务并等待它们完成;task.Factory.StartNew在后台启动新任务。在这两种情况下,实际工作可能是在不同的内核或处理器上完成的。根据任务并行库(TPL)。

我有一个同事,他确信只有parallel.invoke方法允许线程在不同的核心/处理器上执行,而task.factory.startnew可以启动一个新线程,但这个线程只会在一个核心/处理器上调度--所以实际上并不提供并行性。

我找不到任何文件或文章明确说明是否如此。我的同事提到了我正在看的那些文章,比如基于任务的异步编程,我认为这验证了我的理解,但我的同事认为这验证了他的理解。

文档中有时使用术语“并行处理”来指代parallel.invoke,使用术语“异步任务”来指代“task.factory.startnew”,但据我所知,在分配给多个处理器/核的后台也会发生同样的事情。

请任何人帮助澄清情况,如果可能的话,提供文档/文章的链接。

我知道这听起来像是在寻求解决与同事的争论,但我真的希望澄清我是否正确理解了这一点。

共有2个答案

鲁展
2023-03-14

尽管操作系统有时提供“处理器亲和”,但这是一种边缘情况,其使用(或可用性)相当罕见。就我所知,.NET并没有利用这些东西。

您的基础假设必须始终是:“一个可运行的线程/进程将在它喜欢的地方运行”,并且它可以随时从一个CPU资源切换到另一个CPU资源。NET framework在很多方面都为您提供了“更好的”服务,但是底层的调度决策仍然由主机操作系统专门做出。

伯英锐
2023-03-14

其实很容易回答。

task.run()

将指定的工作排队以在线程池上运行....

任务并行库

...此外,TPL还处理工作的分区、线程池上的线程调度、....

使用相同的线程池,线程池如何确定任务类型以限制CPU?它们要么都运行在所有处理器上,要么都运行一个处理器。

额外学分:

这就引出了一个问题,线程池是否知道多核?

答案是惊人的,它不在乎。线程池向操作系统(就像任何使用new Thread()的C#应用程序一样)请求线程,这实际上是操作系统的责任。我想现在已经很清楚了,在所有的抽象中,即使暗示C#可以在默认情况下限制线程的使用方式也是一个相当荒谬的断言。(是的,您可以在您想要的任何核心上运行线程等等,但这不是ThreadPool默认的工作方式)。

我强烈建议阅读StartNew是危险的...TLDR?使用task.run()

 类似资料:
  • 问题内容: 我正在用Java编写多线程应用程序,以提高顺序版本的性能。它是针对0/1背包问题的动态编程解决方案的并行版本。我有一个Intel Core 2 Duo,在不同的分区上都具有Ubuntu和Windows 7 Professional。我在Ubuntu中运行。 我的问题是并行版本实际上比顺序版本花费的时间更长。我认为这可能是因为所有线程都被映射到同一个内核线程,或者它们被分配给了同一个内核

  • 问题内容: 我是Linux内核的新手。 我知道有两个上下文 1.进程上下文,在用户空间或内核空间中运行(例如:作为系统调用的一部分) 2.中断上下文 在什么情况下运行内核线程(与ex:flush任务无关的任何用户线程)? 除了Linux内核中的Process和Interrupt上下文之外,还有其他上下文吗? 问题答案: 内核线程在内核空间中的进程上下文中运行。虽然也有一些内核线程可以处理中断。它们

  • 我正在运行RxJava并创建一个主题以使用方法生成数据。我正在使用Spring。 这是我的设置: 在RxJava流上生成新数据的方式是通过Autowire private SubjectObserver SubjectObserver,然后调用SubjectObserver。发布(newDataObjGenerated) 无论我为subscribeOn()指定了什么 Schedulers.io()

  • 问题内容: 我可以使用一台可以访问10个内核的机器-我想实际使用它们。我习惯在自己的机器上做的事情是这样的: 我要执行10个文件-我们将其称为blah00.fa,blah01.fa,… blah09.fa。 这种方法的问题在于,myProgram一次仅使用1个内核,并且在多核计算机上这样做,我将一次使用10个内核,因此我不会使用mahcine来其最大能力。 如何更改脚本,以使其同时运行所有10个.

  • 问题内容: 假设我为使用版本10内核的OS制作了一个映像,如果我在运行版本9内核的主机OS上为该映像运行一个容器,那么Doc​​ker会表现出什么行为?那版本11呢? 版本的向后兼容性重要吗?我出于好奇而问,因为文档仅讨论“最低Linux内核版本”等。这听起来像主机运行的内核版本超出该最低值无关紧要。这是真的?有警告吗? 问题答案: 假设我为使用版本10内核的操作系统制作映像。 我认为这是一个误解

  • 问题内容: 如何在C程序中知道我的代码在哪个物理处理器和内核上运行?我正在使用Linux和gcc 4.4.3。 问题答案: 您可以根据http://www.kernel.org/doc/Documentation/filesystems/proc.txt检查/ proc // stat文件系统,只需检查task_cpu标志。 没有正确类型和错误检查的示例: