对于 Task.Factory.StartNew 和 Parallel.Invoke,线程可以 运行 在不同的处理器或内核上
Threads can run on different processors or cores for both Task.Factory.StartNew and Parallel.Invoke
我希望阐明我对 .NET 多线程的理解,特别是哪些 .NET 方法创建的线程可能会在 multi-processor/core 系统中的不同处理器或内核上同时执行。
在 .NET TPL 框架中,您可以使用方法 Parallel.Invoke 或 Task.Factory.StartNew 来实现某种并行性。
我的理解是,在这两种情况下,.NET 都会创建新任务(在 Parallel.Invoke 的幕后),然后 .NET 环境将其分配给幕后的托管线程,然后将其分配给线程, CPU 可能会根据工作负载分配给不同的内核或处理器。这两种方法的主要区别在于语义——Parallel.Invoke 执行多个任务并等待它们完成; Task.Factory.StartNew 在后台启动一个新任务。在这两种情况下,实际工作可能在不同的内核或处理器上完成。根据 Task Parallel Library (TPL).
我有一个同事确信只有 Parallel.Invoke 方法允许线程在不同的 cores/processors 上执行,并且 Task.Factory.StartNew 启动一个新线程但是那个线程将只安排在一个 core/processor - 所以实际上并没有提供并行性。
我找不到任何文档或文章明确说明是否属于这种情况。我的同事向我推荐了我正在查看的相同文章,例如 Task-based Asynchronous Programming,我认为这验证了我的理解,但我的同事认为验证了他的理解。
文档有时使用术语 "parallel processing" 来引用 Parallel.Invoke 和 "asynchronous tasks" 来引用 "Task.Factory.StartNew",但据我了解,同样的事情发生在关于分配给多个 processors/cores.
的背景
任何人都可以帮助澄清情况,如果可能的话,链接到 documentation/articles。
我知道这听起来像是在寻求解决与同事争论的方法,但我真的很想澄清我是否理解正确。
其实很容易回答。
Queues the specified work to run on the ThreadPool ....
... In addition, the TPL handles the partitioning of the work, the scheduling of threads on the ThreadPool, ....
使用同一个ThreadPool,ThreadPool如何判断任务的类型来限制CPU?它们要么在所有处理器上都运行,要么在单个处理器上都运行。
加分项:
这引出了一个问题,ThreadPool 多核感知吗?
答案出人意料,不在乎。 ThreadPool asks the operating system(就像任何使用 new Thread()
的 c# 应用程序一样)对于线程,它实际上是 OS 的责任。我认为现在已经很清楚了,所有的抽象甚至暗示 C# 可以 默认 限制线程的使用方式是一个非常荒谬的断言。 (是的,你可以 运行 在你想要的任何核心上创建一个线程等等,但这不是线程池 默认 的工作方式)。
我强烈推荐阅读 StartNew is Dangerous... TLDR?使用 Task.Run()
.
尽管操作系统有时会提供 "processor affinity,",但这是一种边缘情况,它的使用(或可用性)非常罕见。据我所知,.NET 没有使用这些东西。
您的基础假设必须始终是:"a runnable thread/process will run where it damn well pleases," 并且它可能随时从一个 CPU 资源切换到另一个。 .NET 框架在很多方面为您提供了很多东西 "nicer",但底层的调度决策仍然由主机操作系统完全做出。
我希望阐明我对 .NET 多线程的理解,特别是哪些 .NET 方法创建的线程可能会在 multi-processor/core 系统中的不同处理器或内核上同时执行。
在 .NET TPL 框架中,您可以使用方法 Parallel.Invoke 或 Task.Factory.StartNew 来实现某种并行性。
我的理解是,在这两种情况下,.NET 都会创建新任务(在 Parallel.Invoke 的幕后),然后 .NET 环境将其分配给幕后的托管线程,然后将其分配给线程, CPU 可能会根据工作负载分配给不同的内核或处理器。这两种方法的主要区别在于语义——Parallel.Invoke 执行多个任务并等待它们完成; Task.Factory.StartNew 在后台启动一个新任务。在这两种情况下,实际工作可能在不同的内核或处理器上完成。根据 Task Parallel Library (TPL).
我有一个同事确信只有 Parallel.Invoke 方法允许线程在不同的 cores/processors 上执行,并且 Task.Factory.StartNew 启动一个新线程但是那个线程将只安排在一个 core/processor - 所以实际上并没有提供并行性。
我找不到任何文档或文章明确说明是否属于这种情况。我的同事向我推荐了我正在查看的相同文章,例如 Task-based Asynchronous Programming,我认为这验证了我的理解,但我的同事认为验证了他的理解。
文档有时使用术语 "parallel processing" 来引用 Parallel.Invoke 和 "asynchronous tasks" 来引用 "Task.Factory.StartNew",但据我了解,同样的事情发生在关于分配给多个 processors/cores.
的背景任何人都可以帮助澄清情况,如果可能的话,链接到 documentation/articles。
我知道这听起来像是在寻求解决与同事争论的方法,但我真的很想澄清我是否理解正确。
其实很容易回答。
Queues the specified work to run on the ThreadPool ....
... In addition, the TPL handles the partitioning of the work, the scheduling of threads on the ThreadPool, ....
使用同一个ThreadPool,ThreadPool如何判断任务的类型来限制CPU?它们要么在所有处理器上都运行,要么在单个处理器上都运行。
加分项:
这引出了一个问题,ThreadPool 多核感知吗?
答案出人意料,不在乎。 ThreadPool asks the operating system(就像任何使用 new Thread()
的 c# 应用程序一样)对于线程,它实际上是 OS 的责任。我认为现在已经很清楚了,所有的抽象甚至暗示 C# 可以 默认 限制线程的使用方式是一个非常荒谬的断言。 (是的,你可以 运行 在你想要的任何核心上创建一个线程等等,但这不是线程池 默认 的工作方式)。
我强烈推荐阅读 StartNew is Dangerous... TLDR?使用 Task.Run()
.
尽管操作系统有时会提供 "processor affinity,",但这是一种边缘情况,它的使用(或可用性)非常罕见。据我所知,.NET 没有使用这些东西。
您的基础假设必须始终是:"a runnable thread/process will run where it damn well pleases," 并且它可能随时从一个 CPU 资源切换到另一个。 .NET 框架在很多方面为您提供了很多东西 "nicer",但底层的调度决策仍然由主机操作系统完全做出。