java - 当线程数多于内核数时,简单的并行计算会获得更好的结果
问题描述
我有一个简单的 Java 应用程序,它基本上将计数器递增 600M 次。我把这个任务分成了几个线程,每个线程都增加自己的计数器,最后对这些计数器求和。
奇怪的是,拥有比内核更多的线程可以获得更好的性能:
平均计算时间的示例(在具有六个内核的Intel I7-9850H上):
- 有 6 个线程,每个线程都有 100M 增量,产生97 ms
- 有 60 个线程,每个线程有 10M 增量,产生61 ms
AFAIK Java 将每个线程映射到一个真实的系统线程。
任何想法为什么会发生这种情况?
编辑:
可能是因为我的计算机有许多其他正在运行的进程和线程,所以 60 个线程与所有其他习惯的竞争比只有 6 个线程竞争 CPU 资源要好?
增量方法的代码:
private static void incrementWithLockFree(long increments, int threads) throws InterruptedException {
final long[] numbers = new long[threads];
ExecutorService threadPool = Executors.newFixedThreadPool(threads);
for (int task = 0; task < threads; task++) {
int finalTask = task;
threadPool.submit(() -> {
for (long increment = 0; increment < increments; increment++) {
numbers[finalTask]++;
}
});
}
threadPool.shutdown();
threadPool.awaitTermination(1, TimeUnit.DAYS);
long number = 0;
for (long num : numbers) {
number += num;
}
System.out.println(number);
}
解决方案
在我的系统上,更少的线程性能更好。
是否可能是因为我的计算机有许多其他正在运行的进程和线程,所以 60 个线程与所有其他习惯的竞争比只有 6 个线程竞争 CPU 资源要好?
是的。
如果这是一个真实的用例,请查看LongAdder
针对多线程计数器场景进行了优化的 。
推荐阅读
- javascript - 访问 js 文件中的隐藏 API 密钥(git hub 页面)
- sql - 具有相似但不同数据/键的两个不同表的联接语句
- r - 优化没有循环的时间序列操作:有可能吗?
- javascript - JSX 没有在 div 中显示第二个 p
- python-3.x - Pyinstaller - 在生成多文件 dist 以减小大小后作为第二步打包到一个文件中
- node.js - 测试合约时运行断言测试失败
- sql - 在查询项目列表时,我可以对每个项目应用过滤器吗?
- c# - Razor View 将错误的 Id 传递给 OnPost 方法
- oracle - ORACLE APEX:动态更改图表
- wordpress - 古腾堡属性未正确保存或检索?