当我执行多个优于 Runtime.getRuntime().availableProcessors()) 的并行线程时,为啥我的 Java 程序运行得更快?
Posted
技术标签:
【中文标题】当我执行多个优于 Runtime.getRuntime().availableProcessors()) 的并行线程时,为啥我的 Java 程序运行得更快?【英文标题】:How come my Java program goes faster when I execute a number of parallel threads superior to Runtime.getRuntime().availableProcessors())?当我执行多个优于 Runtime.getRuntime().availableProcessors()) 的并行线程时,为什么我的 Java 程序运行得更快? 【发布时间】:2015-02-19 22:53:21 【问题描述】:我对如何在 Java 中执行并行线程进行了一些研究。
我找到了一个简单的解决方案,即使用ExecutorService
类。
它基本上是通过调用以下方式来使用的:
ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
每个线程执行一个简单的任务,例如System.out.println()
。
有人告诉我Runtime.getRuntime().availableProcessors()
返回处理器的数量,这基本上是能够运行您的代码的执行引擎的数量,如果使用超线程,物理上不同的处理器或逻辑处理器。
但是,当我改用以下行时:
ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*2);
我的程序实际上运行得更快(尽管我还没有计算出确切的运行时间,只是观察了明显的速度变化)。
这怎么可能?另外,如果我将这个数字乘以 3,它的速度会更快,即使速度随着因子的增加而停止增加。
我的电脑是运行在 Yosemite 上的 MacBook Pro,配备 2.2 GHz Intel Core i7 处理器。
【问题讨论】:
您的任何线程是否执行 I/O?机器上是否正在运行其他进程? 这种JAVA全大写的趋势是什么?它是“Java”。 【参考方案1】:简单的任务(调用System.out.println()
)涉及与外部世界的交互,它可能会被阻止等待(例如)显示设备或磁盘响应。
一个任务也可能与其他任务同步,并且可能必须等待另一个线程上的活动才能做某事,或者等待共享变量的更新。
“线程数 ~= 内核数”规则只是一个经验法则。只有当线程真正独立于彼此和外部影响时,它才具有预测性。对于现实世界的多线程应用程序,如果您的目标是最大限度地提高性能,则需要针对应用程序、平台和问题调整线程数。
【讨论】:
【参考方案2】:ExecutorService es = Executors.newFixedThreadPool(noOfThreads);
使用输入编号创建一个固定的线程池。在某些情况下,更多线程会提供更好的性能,具体取决于线程执行的任务。
在以下陈述中
ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()*2);
您只是将 cpu 的数量用作倍数,但实际上并未明确涉及可用的 cpu。它只是产生差异的线程号。
【讨论】:
【参考方案3】:使用比可用处理器更多的工作线程运行就像有超过六名球员适合打曲棍球比赛一样。如果一名球员需要离开冰场,那么另一名球员准备离开替补席并接替他的位置。
这就是为什么我问你的任何线程是否执行 I/O。执行 I/O 将阻塞线程,直到 I/O 操作完成。如果您的工作线程多于可用处理器,那么当一个线程退出等待 I/O 时,另一个线程将准备好接替它并继续使用 CPU。这样,您将更好地利用可用周期。
不要忘记分页也是 I/O。
我还询问了这台机器上是否还有其他进程正在运行。桌面操作系统根据一些“公平”概念来调度线程。我不知道 Mac OS 上的“公平”是什么意思,但如果这意味着操作系统试图给每个 thread 公平的 CPU 时间份额(而不是给每个 process 一个公平的份额),那么拥有更多线程的程序将比拥有更少线程的程序获得更大的份额。这仅在有其他程序实际使用 CPU 时才有意义。
【讨论】:
以上是关于当我执行多个优于 Runtime.getRuntime().availableProcessors()) 的并行线程时,为啥我的 Java 程序运行得更快?的主要内容,如果未能解决你的问题,请参考以下文章
工具PostgreSQL的NoSQL特性表现抢眼,多个方面优于MongoDB
TensorFlow 的 ParameterServerStrategy 何时优于其 MultiWorkerMirroredStrategy?