并发方法是否是加速长迭代的好主意?

时间:2010-08-27 20:16:55

标签: java concurrency recursion iteration nested-loops

我有一个应用程序会进行迭代,以便随着时间的推移在图形上创建点。 当我收集x轴上每个点的数据时,我还必须执行递归查找,这实际上意味着我在另一个循环中有一个循环。这不是很好的扩展。我没有看到很多在迭代中使用“分而治之”解决方案的例子。我正在考虑使用Java的Executor并发框架在它自己的线程中运行每个循环,等待答案,收集结果并返回它们。我得到的初步测试结果似乎没那么快。我知道我应该展示一些代码,但我首先要知道的是,与我可能不熟悉的更好的方法相比,这种方法是否有价值。 提前谢谢!

添加一些groovyish / javaish伪代码以帮助思考:

class Car {
    id
    model 
    make
    weight
}

for (number in listOfImportantCarIDs) {
    Car car = carsMap.get(number) // find the car we care about
    String maker = car.make //get it's 'parent' 

    // get amount of all related cars
    Iterator<Car> allcars = carsMap.values().iterator();
    while (allcars.hasNext()) {
        Car aCar = alldocs.next();
        if (maker.equals(aCar.make)) {
            totalCarCount++;  // increment total related cars 
            BigDecimal totalWeightofAllCars = totalWeightofAllCars.add(aCar.getWeight()); // add weight to total

            // a ghetto cache to prevent double  counting
            countedMaufacturers.add(make); 
        }     
    }
}

7 个答案:

答案 0 :(得分:2)

如果计算每个x值的y值的任务对于每个x值都是完全原子的,那么我认为这非常适合执行程序服务。即使在对解决方案进行了大量推理之后,大多数性能问题都需要进行测量。 CPU绑定问题的最佳线程数是p或p + 1,请记住这一点。

您是否看过Dynamic Programming方法?它适用于您的问题吗?从本质上讲,递归意味着您一遍又一遍地解决相同的问题,但输入值略小。当运行相同递归算法的多次迭代时,程序往往会重新解决相同的问题。相反,动态编程方法可能会将解决方案存储在缓存中,并在第二次计算解决方案之前引用缓存。

在不知道确切问题的情况下,很难给出确切的答案。

答案 1 :(得分:2)

这取决于什么使你的循环变慢。他们正在执行数据库查询吗访问硬盘?否则做一些导致他们等待外部I / O操作的事情?在这种情况下,你最好的选择是开始添加线程,直到你不再看到它们的回报,你基本上必须调整它。

如果它们因为Java中的内存中发生原始处理而变慢,那么你可以尝试在你的机器上为每个CPU核心添加一个线程,但除此之外可能看不到多少好处。

答案 2 :(得分:2)

使用线程会以一些小的常数因素加速您的应用程序,代价是线程间通信的显着增加的复杂性。如果存在更好的算法,那么可以节省数量级。因此,我强烈建议您首先验证确实没有亚二次算法来解决您的问题。

也许如果您详细说明了您要解决的问题以及当前的解决方案,我们可以在这里提供帮助。

编辑:善良,找到一个更好的算法并不难:

for (Car car : cars {
    Stats s = stats.get(car.maker);
    if (s == null) {
        s = new Stats();
        stats.put(car.maker, s);
    }
    stats.count++;
    stats.totalWeight+=car.weight;
}

for (Car car in importantCars) {
    stats.get(car.maker);
}

对于每辆重要的汽车,没有必要为所有汽车进行迭代,只是为了找到那些具有相同制造商的汽车......

答案 3 :(得分:1)

如果您的“源”数据未被您的算法修改或每次迭代仅对其自己的数据进行操作(不会更改附近的数据),则可以在双核上提供(最大)2倍速度提升。

这不是一个很好的解决方案,随着当前解决方案的时间增长,如果您处于双嵌套循环中,这将增长到1/2,这仍然相当昂贵。 O(X ^ 2/2)仍然几乎等于O(X ^ 2)。

如果你能找到一种方法来优化你的算法,这种算法具有更高的真正成功潜力,而且可能会花费大量时间来修复bug。

答案 4 :(得分:0)

沿X轴的每个点可以并行计算吗?如果是这样,那就是通过多线程提高性能的机会。

Fork-Join框架将使这种程序变得简单。您可以获得早期版本,或在某种程度上自己模仿。

答案 5 :(得分:-1)

“另一个循环中的循环”应响铃;)。外循环总是在等待内循环。所以这是一个串行执行,使用线程不会改变一点。除非每个循环将结果写入中央服务,否则可以通过x轴上的后续事件(循环)进行查询。所以这项服务将是有条不紊的......

答案 6 :(得分:-2)

我不认为并发可以使您的应用程序更快。它可以帮助您在应用程序中运行多个任务,但它不会使它们更快。

我的经历: 尝试摆脱递归调用,这是使应用程序更快的最佳方式。