线程可以在Task.Factory.StartNew和Parallel.Invoke的不同处理器或内核上运行

时间:2018-11-06 21:49:24

标签: c# multithreading parallel-processing task-parallel-library

我希望阐明我对.NET多线程的理解,尤其是,哪种.NET方法创建的线程可能在多处理器/核心系统中的不同处理器或核心上同时执行。

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

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

我有一位同事深信,只有Parallel.Invoke方法才允许线程在不同的内核/处理器上执行,而Task.Factory.StartNew启动一个新线程,但该线程将仅在一个内核上进行调度/处理器-因此实际上并没有提供并行性。

我找不到任何明确说明是否存在这种情况的文档或文章。我的同事向我推荐了我正在看的相同文章,例如Task-based Asynchronous Programming,我认为这些文章可以验证我的理解,但我的同事认为可以验证他的理解。

该文档有时会使用“并行处理”一词来表示Parallel.Invoke,而使用“异步任务”一词来表示“ Task.Factory.StartNew”,但据我了解,同一件事在后台发生分配给多个处理器/内核。

如果可能的话,有人可以帮助您澄清情况吗?请提供文档/文章的链接。

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

2 个答案:

答案 0 :(得分:2)

实际上很容易回答。

Task.Run()

  

将指定的工作排队以在ThreadPool上运行...。

Task Parallel Library

  

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

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

额外功劳:

这引出了一个问题, ThreadPool多核是否知道

答案令人惊讶,它不在乎。 ThreadPool asks the operating system(就像使用new Thread()的所有c#应用程序一样)用于线程,它实际上是操作系统的责任。我认为,到现在为止,所有暗示甚至暗示C#可以默认限制线程使用方式的抽象都相当荒谬。 (是的,您可以在所需的任何内核上运行线程,等等,但这不是 default 的方式,ThreadPool的工作原理。)

我强烈建议您阅读StartNew is Dangerous ... TLDR?使用Task.Run()

答案 1 :(得分:0)

尽管操作系统有时会提供“处理器相似性”,但这是一种极端情况,其使用(或可用性)非常罕见。据我所知,.NET不会使用这些东西。

您的基本假设必须始终是:“一个可运行的线程/进程将在该死的地方运行,”它可能随时从一种CPU资源切换到另一种CPU资源。 .NET框架通过许多方式为您提供了很多“更好的东西”,但是底层的调度决定仍由主机操作系统唯一地做出。