java - 为了获得最大性能,线程池的大小应该是多少?

标签 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。

最佳答案

你是对的,你应该考虑让你的核心饱和。不过,最佳答案将超过 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 个核心的情况下任何时候使用的预期核心数量。

关于java - 为了获得最大性能,线程池的大小应该是多少?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38817220/

相关文章:

java.lang.IllegalStateException : Activity has been destroyed -- Android fragment 错误

c++ - 并发编程C++?

python-3.x - Goroutines vs asyncio 任务 + CPU 绑定(bind)调用的线程池

java - 缓存失效 Postgres NOTIFY 与轮询

java - 从 XSD 生成 pojo 时删除 @XmlElement 注释

c# - 如何在多个线程之间共享一个 mysql 连接?

java - 如何通过java监听新的数据库记录

sql-server - 添加主键标识列可以解决死锁问题吗?

java - 方法 Socket(String, int) 未定义类型

java - 使用 C3P0 和 Hibernate/Spring 创建的许多线程