线程池的大小应该达到最大性能?

时间:2016-08-07 18:26:19

标签: java multithreading concurrency

我最近遇到了这个问题进行评估:

ExecutorService threadpool = Executors.newFixedThreadPool(N);

for(Runnable task : tasks){
    threadpool.submit(task);
}

每个任务花费25%用于计算,75%用于I / O.假设我们正在研究四核机器(没有超线程),那么线程池N的大小应该是什么,以在不浪费线程的情况下实现最大性能? (假设我们有无限的I / O容量)

我猜测16,因为机器具有无限的I / O意味着我们可以完全专注于CPU。每个任务在运行时使用四分之一的CPU。这意味着,我们可以运行四个任务来使一个CPU内核饱和,并使四核机器上的N = 16。

更新:此问题的选项为2,4,5,6,7,8,12和16。

2 个答案:

答案 0 :(得分:1)

你应该考虑使内核饱和是正确的。不过,最好的答案是超过16个。如果您只有16个线程,那么CPU要求不会完全对齐,以便所有核心始终在使用。

所以最好的答案是> 16,但也足够小,不会显着增加个人任务完成时间,强加显着的线程切换成本,或浪费大量内存。

如果你在课堂上学到了这一点,那么你的教授可能会给你倍增的用法作为经验法则"。他会期待你记住它并在这里应用它。

我通常使用average_demand = 2 * num_cores,因此选择32个线程。这在大多数情况下效果很好。当平均CPU需求是核心数量的两倍时,核心利用率将非常接近100%。

此外,在这种情况下,每个任务的CPU部分平均只获得1/2核心,因此需要两倍的时间......但它只占工作的25%,因此任务完成时间仅比最佳值高出13%。

我使用的2倍默认值几乎总是高于最佳数量,但它也几乎总是足够低,不会产生显着的额外开销。如果您知道您的任务受CPU严重限制,那么您可以放心地减少这个数字。

如果你真的想找到最佳值,那么你可以测量它,但是当你在合适的范围内时,它不会产生很大的不同。

-

P.S注意:' average_demand'我上面使用的是在给定N个线程和N个核心的情况下随时可以使用的预期核心数。

答案 1 :(得分:1)

虽然这个问题没有严格的正确或错误的答案,但主观上的好处是:

32个帖子

你必须考虑概率。 现在让我们考虑一个CPU核心和独立线程:

一个线程有25%的机会在任何给定时间进行计算。 如果你有2个独立的线程(概率事件),至少有一个CPU工作的概率不是50%而是7/16(43.75%)。 (如果您对此不确定,则应刷新其中一些probability skills)。

你可能会看到这是怎么回事。对于P为100%,线程数必须是无限的。所以我们必须做出有根据的猜测: 4个螺纹的P为~68%,8个螺纹~90%。如果算上计数现在真的没有效果,所以我们定居在8.这是一个核心。我们有4个CPU内核,所以我们可以将它乘以4得到最终答案:32。

相关问题