据我所知,Plinq通过核心数来决定打开多少个线程(每个线程在不同的核心上)。
__________
Core 1
Core 2
Core 3
Core 4
___________
所以,如果我有一个Plinq任务,要找到所有前1000个素数,Plink将打开一个新的线程。Thread on each Core
以求效率最大化。
所以在这里,每个核心将运行在10004个数上,寻找质数的逻辑。
然而,我读到一个阻塞操作,如 IO
应与 WithDegreeOfParallelism
这样cpu就不会认为这是一个密集型的cpu操作,并允许它使用 more
线程比 cores
.
问题:
1)是否准确?我的理解是否正确?
2)如果我设置 WithDegreeOfParallelism (7)
所以它肯定会使用所有4个核心,但其他3个呢?(7-4)它们会在哪里运行?在哪些核心上?
首先,.Net不选择哪个核执行哪个线程,是操作系统选择的。如果系统中没有其他CPU密集型的应用程序,你可以预期每个线程将在一个单独的核上执行。但如果有其他应用,操作系统可能会例如决定将你的所有线程运行在一个核心上,在它们之间切换。
而且比这更复杂。一个线程通常不会运行在一个核上,操作系统会一直在核与核之间切换。例如,看看下面这张来自任务管理器的截图,它显示了一个单线程CPU密集型应用程序的执行情况。
你会注意到,这个单线程在我的4个核心上都执行了,并且在运行的几秒钟内利用了每个核心的大约25%。
.Net对你的计算机的CPU使用情况一无所知,所以它假设做CPU密集型工作的最佳线程数与核心数相同。
我不知道PLINQ到底是如何工作的,但我不会期望在你的例子中每个核心都能准确地产生10004个质数。如果一个线程已经产生了它应得的质数,而另一个线程还没有完成,那么让第一个线程保持空闲状态就不是很有效率。
是的,对于IO操作,最佳的线程数并不取决于核数,所以你应该手动设置并行度。(别忘了,最佳线程数可能是1,硬盘在顺序读取时是最快的,而不是在许多文件之间来回寻找)。
如果你设置了 WithDegreeOfParallelism(7)
它一定会用7 线程 同样,也不能保证核心数量)。操作系统将决定如何在你的4个核心上运行这7个线程,如果这些线程都是CPU密集型的,它很可能会给每个线程47≈57%的核心。如果这些线程都是CPU密集型的,它很可能会给每个线程47%≈57%的核心。如果它们是IO绑定的,它将在任何一个刚刚可用的核心上执行刚刚唤醒(解封)的线程的代码。
而 WithDegreeOfParallelism()
确实设置了确切的线程数,而不是最大的线程数,见Stephen Toub的 ParallelOptions.MaxDegreeOfParallelism
与PLINQ的 WithDegreeOfParallelism
.