【发布时间】:2012-06-01 07:59:30
【问题描述】:
我正在尝试使用Parallel.For 来加快计算速度。我有一个具有 8 个内核的 Intel Core i7 Q840 CPU,但与顺序 for 循环相比,我只能获得 4 的性能比。这是否与 Parallel.For 一样好,或者可以对方法调用进行微调以提高性能?
这是我的测试代码,顺序:
var loops = 200;
var perloop = 10000000;
var sum = 0.0;
for (var k = 0; k < loops; ++k)
{
var sumk = 0.0;
for (var i = 0; i < perloop; ++i) sumk += (1.0 / i) * i;
sum += sumk;
}
并行:
sum = 0.0;
Parallel.For(0, loops,
k =>
{
var sumk = 0.0;
for (var i = 0; i < perloop; ++i) sumk += (1.0 / i) * i;
sum += sumk;
});
我正在并行化的循环涉及使用“全局”定义的变量sum 进行计算,但这应该只占并行化循环内总时间的一小部分。
在 Release 构建(“优化代码”标志设置)中,顺序 for 在我的计算机上循环需要 33.7 秒,而Parallel.For 循环需要 8.4 秒,性能比仅为 4.0。
在任务管理器中,我可以看到顺序计算时 CPU 使用率为 10-11%,而并行计算时仅为 70%。我试图明确设置
ParallelOptions.MaxDegreesOfParallelism = Environment.ProcessorCount
但无济于事。我不清楚为什么不将所有 CPU 功率都分配给 并行 计算?
我注意到在 SO before 上提出了类似的问题,结果更令人失望。但是,该问题还涉及第三方库中较差的并行化。我主要关心的是核心库中基本操作的并行化。
更新
在一些 cmets 中向我指出,我使用的 CPU 只有 4 个物理内核,如果启用了超线程,系统可以看到 8 个内核。为此,我禁用了超线程并重新进行了基准测试。
使用超线程禁用,我的计算现在更快,并行和(我认为是)顺序for 循环。 for 循环期间的 CPU 使用率高达大约。在Parallel.For 循环期间为 45% (!!!) 和 100%。
for 循环的计算时间为 15.6 秒(比启用超线程时快两倍多),Parallel.For 的计算时间为 6.2 秒(比启用超线程时快 25% 启用)。 Parallel.For 的性能比现在只有 2.5,在 4 个真实内核上运行。
因此,尽管禁用了超线程,但性能比仍然大大低于预期。另一方面,在for 循环期间 CPU 利用率如此之高是不是很有趣?在这个循环中是否也存在某种内部并行化?
【问题讨论】:
-
并行循环不需要锁定 sum 变量吗?
-
@SteveB 我相信你是对的。但是,显式锁定不会提高性能,对吧? :-)
-
你确定你有 8 个核心吗?根据this 的说法,例如,i7-840QM 有 4 个内核,由于多线程能力,操作系统可见为 8 个。
-
超线程会欺骗你有 8 个内核的操作系统。您可以在 BIOS 中将其关闭。
-
超线程技术在许多程序的日常工作中都能很好地工作。正如@Magnus 所说,它会“愚弄”操作系统,但会提高它在特定工作负载中的速度。少量核心的问题是,如果您执行大量“数据”特定工作 - 大量读取和写入磁盘,那么工作核心必须等待此过程完成。当您每 1 个物理核心有 2 个逻辑核心时,很有可能当一个任务正在等待数据时,核心可以用于其他工作。看这个答案superuser.com/questions/279629/…
标签: c# performance task-parallel-library