IT源码网

Java ForkJoinPool 未利用所有 CPU 核心

pengyingh 2025年01月19日 程序员 54 0

我正在虚拟墙的节点上运行以下代码。该节点拥有 32 个 Intel Xeon E7/E5 内核和 128GB RAM。监控 CPU 使用率表明该节点远未达到满负荷运行。由于节点大小的原因,该问题与大多数 fork-join 问题不同。有时,节点的多个核心上的 CPU 负载超过 20%,显示出并行性的迹象,但我似乎无法让它使用更多资源。

提供一些背景信息;该问题是 111 个节点的图中的最大化问题 (Parcs/parken)。每个公园内都隐藏着许多鸡蛋。随着每一秒的过去,这个数字呈指数下降。目标是在时间到期之前获得尽可能多的鸡蛋。 “opl”是我使用贪婪算法找到的解决方案,因此为了缩小我们的递归树,我只允许当我们发现最多 5 个鸡蛋比我们的贪婪算法同时发现的鸡蛋少时才允许递归。

我熟悉(多)线程,但距离专家还很远。我以前没有使用过很多ForkJoinPools。我还尝试将 ForkJoinPool 参数设置为 16/32,但没有成功。

Example of current core-load

主要:

Algoritmes.AlgoritmeRecursive.run(new AlgoritmeRecursive(parken, tabel, opl, 22, 1000, 0, 0))); 

类(class):

public static class AlgoritmeRecursive extends RecursiveTask<Double> { 
    private ArrayList<Park> parken = new ArrayList<Park>(); 
    private double[][] afstandenTabel; 
    private double[][] oplossing; 
    private int startpark; 
    private double duur; 
    private double eieren; 
    private int time; 
 
    AlgoritmeRecursive(ArrayList<Park> parken, double[][] afstandenTabel, double[][] oplossing, int startpark, double duur, double eieren, int time) { 
        for (Park p : parken) { 
            this.parken.add(new Park(p)); 
        } 
        this.afstandenTabel = afstandenTabel; 
        this.oplossing = oplossing; 
        this.startpark = startpark; 
        this.duur = duur; 
        this.eieren = eieren; 
        this.time = time; 
    } 
 
    public static double run(AlgoritmeRecursive ar) { 
        ForkJoinPool pool= new ForkJoinPool(); 
        return pool.invoke(ar); 
    } 
 
    protected Double compute() { 
        if (duur < 1.0) return eieren; 
 
        double gevonden = 0; 
 
        /* startpark zoeken adhv gegeven naam */ 
        for (Park p : parken) { 
            if (p.getId() == startpark) { 
                gevonden = p.verwachtAantalEieren(40, 0); 
                p.updateEggs(p.getEggs() * exp((-1.0/10800.0) * ((p.getStartEggs()/20.0) + 40.0))); 
            } 
            else { 
                p.updateEggs(p.getEggs() * exp((-1.0/10800.0) * (p.getStartEggs()/20.0))); 
            } 
        } 
        double score = eieren; 
        for (Park p : parken) { 
            if (p.getId() == startpark && eieren >= (oplossing[1000-(int)duur][1] - 5)) { 
                AlgoritmeRecursive ar = new AlgoritmeRecursive(parken, afstandenTabel, oplossing, startpark, duur-1, eieren + gevonden, time+1); 
                ar.fork(); 
                double res = ar.join(); 
                if(res > score) score = res; 
            } 
            else if (duur-afstandenTabel[startpark][p.getId()] > 60.0 && time > 120.0 && eieren >= oplossing[1000-(int)duur][1] && gevonden < p.verwachtAantalEieren(40,afstandenTabel[startpark][p.getId()])){ 
                AlgoritmeRecursive ar = new AlgoritmeRecursive(parken, afstandenTabel, oplossing, p.getId(), duur-afstandenTabel[startpark][p.getId()], eieren, 0); 
                for (Park p2 : ar.parken) { 
                    p2.updateEggs(p2.getEggs() * exp((-1.0/10800.0) * (p2.getStartEggs()/20.0) * (afstandenTabel[startpark][p.getId()]-1))); 
                } 
                ar.fork(); 
                double res = ar.join(); 
                if(res > score) score = res; 
            } 
        } 
        return score; 
    } 
    public double exp(double x) { 
          x = 1d + x / 256d; 
          x *= x; x *= x; x *= x; x *= x; 
          x *= x; x *= x; x *= x; x *= x; 
          return x; 
    } 
} 

请您参考如下方法:

我自己对此也不是很熟悉,但是对 ar.join() 的调用是否会让您的 RecursiveTask 等待子任务完成?如果是这种情况,您的其他任务将不会在前一个任务运行完成之前开始。

您可以尝试将正在运行的任务存储在列表中,然后再将它们加入。这有望确保所有子任务在等待之前就开始运行。

类似这样的东西(修改compute中的第二个循环):

List<AlgoritmeRecursive> tasks = new ArrayList<>(); 
 
for (Park p : parken) { 
    if (p.getId() == startpark && eieren >= (oplossing[1000-(int)duur][1] - 5)) { 
 
        AlgoritmeRecursive ar = new AlgoritmeRecursive(parken, afstandenTabel, oplossing, startpark, duur-1, eieren + gevonden, time+1); 
        ar.fork(); 
        tasks.add(ar); // Adding the running task to the list. 
 
    } else if (duur-afstandenTabel[startpark][p.getId()] > 60.0 && time > 120.0 && eieren >= oplossing[1000-(int)duur][1] && gevonden < p.verwachtAantalEieren(40,afstandenTabel[startpark][p.getId()])){ 
 
        AlgoritmeRecursive ar = new AlgoritmeRecursive(parken, afstandenTabel, oplossing, p.getId(), duur-afstandenTabel[startpark][p.getId()], eieren, 0); 
        for (Park p2 : ar.parken) { 
            p2.updateEggs(p2.getEggs() * exp((-1.0/10800.0) * (p2.getStartEggs()/20.0) * (afstandenTabel[startpark][p.getId()]-1))); 
        } 
        ar.fork(); 
        tasks.add(ar); // Adding the running task to the list. 
 
    } 
} 
 
double score = eieren; 
for(AlgoritmeRecursive task : tasks) { 
    double res = ar.join(); 
    if(res > score) score = res; 
} 
 
return score; 


评论关闭
IT源码网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!