我的程序使用如下所示的 fork/join 来运行数千个任务:
private static class Generator extends RecursiveTask<Long> {
final MyHelper mol;
final static SatChecker satCheck = new SatChecker();
public Generator(final MyHelper mol) {
super();
this.mol = mol;
}
@Override
protected Long compute() {
long count = 0;
try {
if (mol.isComplete(satCheck)) {
count = 1;
}
ArrayList<MyHelper> molList = mol.extend();
List<Generator> tasks = new ArrayList<>();
for (final MyHelper child : molList) {
tasks.add(new Generator(child));
}
for(final Generator task : invokeAll(tasks)) {
count += task.join();
}
} catch (Exception e){
e.printStackTrace();
}
return count;
}
}
我的程序大量使用第三方库来实现 isComplete 和 extend 方法。extend 方法也使用了本地库。就 MyHelper 类而言,任务之间没有共享变量或同步。
我使用来自 linux 的 taskset 命令来限制我的应用程序使用的内核数量。我通过使用大约 10 个内核(比如大约 60 秒)获得了最佳速度。这意味着使用超过 10 个内核会导致应用程序变慢,因此 16 个内核与 6 个内核在同一时间内完成(大约 90 秒)。
我更困惑,因为选定的核心 100% 忙(不时进行垃圾收集除外)。有谁知道什么会导致这样的减速?我应该在哪里解决这个问题?
PS:我也在 Scala/akka 和使用 ThreadPoolExecutor 中进行了实现,但结果相似(虽然比 fork/join 慢)
PPS:我的猜测是,在 MyHelper 或 SatCheck 的深处,有人越过了内存屏障(中毒缓存)。但是我怎样才能找到并修复或解决它呢?