我试图创建一个简单的示范使用‘并行LINQ’(PLINQ)。在C#中,我有两个版本的任务:
var result = Enumerable.Range(1,1000000).Where(x => IsPrime(x)).ToList();
var result = Enumerable.Range(1,1000000).AsParallel().Where(x => IsPrime(x)).ToList();并使用System.Diagnostics.StopWatch对这两个版本进行计时。在我的机器上(4个核心,8个逻辑处理器),第一个需要大约。114秒,而PLINQ版本需要大约。30秒我知道的足够多,不会期望得到8倍的改进,尽管我想,考虑到任务的长度和纯度(无I/O),我会比3.8X更好。
但是,看看使用资源监视器的单个核心使用情况,我对我所看到的感到惊讶。
在任务开始之前,处理器的总体利用率是5-10%。当任务运行时,在启动高峰之后,我看到:
第二个场景对我来说更有意义,虽然我想我会看到7个核心在计算查询,第八个核心在执行所有其他事情。
对于第一个版本,我(天真地)期望看到一个核心运行平平,而其他(运行各种后台进程)更少。有人能解释一下发行版是如何管理的吗?为什么--在这样的纯处理场景中--并行性的收益不会更大呢?
发布于 2022-09-28 15:09:25
对于第一个版本,我(天真地)期望看到一个核心运行平平,而其他(运行各种后台进程)更少。有人能解释一下发行版是如何管理的吗?
操作系统将在几个核心周围移动一个高使用率的线程,部分原因是为了分配热负荷。但是调度是一个非常复杂的问题,CPU并不能使调度变得更容易,有些内核共享L2缓存,有些内核在不同的芯片上,因此可以根据操作系统、CPU、总体系统负载等来获得不同的行为。
第二个场景对我来说更有意义,虽然我想我会看到7个核心在计算查询,第八个核心在执行所有其他事情。
该系统将使用所有可用的核心,它不“保留”任何核心的“其他东西”。如果有8个线程计算质数,如果内核可用,它将对所有线程进行调度。下次有时间片可用时,调度程序将使用一些逻辑来决定下一步应该运行哪个线程。
但是在多个核上运行代码总是有一些开销。95%的比例,你的报价实际上是非常好的。
还请注意,仅仅因为windows列出了一个100%使用率的核心,并不意味着它实际上一直在做有用的工作,它可能会等待内存,在等待锁时旋转一点,或者其他对程序的进度没有真正贡献的东西。因此,如果您正在进行硬核优化,则需要深入研究更细粒度的诊断信息,以确定是否能够更有效地利用处理器。
我知道得够多了,不能指望有8倍的进步。
你只有4个物理核心。逻辑/物理核(通常称为同步多线程(SMT) )的思想是允许CPU在两个线程(或在某些情况下更多)之间快速切换。因此,如果一个线程由于等待内存读取而无法执行,CPU内核可以在另一个线程上工作。或者,如果一个线程主要是整数工作,而另一个线程主要是浮点,CPU内核可以同时运行这两个线程,因为它们使用不同的执行资源。如果两个线程都执行类似的工作,并且可以通过缓存完成工作,并且内存访问很少,那么这一点就不太有用了。您的IsPrime-method听起来似乎很少能从SMT中获益。
https://softwareengineering.stackexchange.com/questions/441289
复制相似问题