【发布时间】:2015-11-07 21:22:17
【问题描述】:
我们都知道,为了真正执行异步操作,我们的机器必须有多个核心,每个核心都将运行自己的线程来执行其任务。
让我们从一个示例开始,其中我们有一个 四核 cpu 和 4 个任务。为了使用 C# 以真正的并行方式运行我们的四个任务,我们必须像这样分别创建和运行 4 个任务:
public static void Main()
{
// Define and run the tasks.
Task[] tasks = {
Task.Run( () => WorkA() ),
Task.Run( () => WorkB() ),
Task.Run( () => WorkC() ),
Task.Run( () => WorkD() )
}
Task.WaitAll(tasks);
}
在此示例中,TPL 将为每个任务提供来自 ThreadPool 的线程,并在可能的情况下在不同的处理器中运行每个线程。 (希望我是对的)
场景:
假设我们有 四核 cpu 和 6 个任务,我们编写了以下代码:
public static void Main()
{
// Define and run the tasks.
Task[] tasks = {
Task.Run( () => WorkA() ),
Task.Run( () => WorkB() ),
Task.Run( () => WorkC() ),
Task.Run( () => WorkD() ),
Task.Run( () => WorkE() ),
Task.Run( () => WorkF() )
}
Task.WaitAll(tasks);
}
TPL 会知道什么是最充足的线程并在其中安排任务吗? (考虑核心的状态和任务的负载差异)
例如:
- 总共 3 个线程 - 每个线程 2 个任务。 (假设一个核心很忙)
- 总共 4 个线程 - 3 个线程 - 每个线程 1 个任务,最后 3 个任务 一个。
- 总共 6 个线程 - 每个线程 1 个任务。
TPL 如何执行负载平衡?为了提供最佳负载平衡,TPL 需要考虑什么。
【问题讨论】:
-
任务调度程序永远不会知道什么是最佳策略。当他知道为时已晚,因为工作已经完成。所以有很多猜测,测量cpu核心工作量和任务创建选项。仅此而已 - 没有未来的愿景或任何内置的魔法
-
任务调度程序是一种通用工具,它试图在不知道必须完成什么样的工作的情况下尽可能快地完成工作。如果你更了解你的工作并且负载更好,你应该构建自己的专门线程驱动的工作工作者来获得最后百分比的性能:o)
-
扩展 Rufo 的有效观点是,由于显式创建线程的每个线程开销,线程的启动成本很高。使用内置任务线程池允许在重用内置线程池的同时创建许多较小的较短任务,并将您的代码从管理线程池以及调度和同步等中解放出来。因此,如果您有 1000 个不相关的任务,请使用内置的在线程池中。如果您有 5 个独立组,每组 200 个相关操作,请使用您自己的 5 个线程池。
标签: c# multithreading task-parallel-library multicore multitasking