首页 > 解决方案 > Java中的嵌套for循环优化-流替代导致不同的结果

问题描述

我尝试在 Java 中并行运行 13 个 for 循环,并尝试用 DoubleStream 重写它们。问题是由相同代码提供的输出,但使用“for”循环与流替代方案提供的输出不同。

另一个问题是“for”循环的实现需要很多时间,我需要改进它。我认为流方法是不正确的,因为我所做的操作是串行的,线程的顺序是随机的,所以处理做得不太正确。有什么方法可以获得相同的结果或并行化 for 循环?我的代码如下:

        DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(a -> {
            System.out.println("Iteration " + a + " min var " + wrapperMinVariation.minVariation + "values: " + wrapperMinA.minA + " " + wrapperMinB.minB);
            DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(b -> {
                System.out.println("Iteration " + a +" "+ b +" min var " + wrapperMinVariation.minVariation + "values: " + wrapperMinA.minA + " " + wrapperMinB.minB);
                DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(c -> {
                    DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(d -> {
                        DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(e -> {
                            DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(f -> {
                                DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(g -> {
                                    DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(h -> {
                                        DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(m -> {
                                            DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(n -> {
                                                DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(o -> {
                                                    DoubleStream.iterate(0, x -> x + 0.2).limit(5).parallel().forEach(p -> {
                                                        double variation = 0;
                                                        for (int i = 0; i < wrapper.list.size(); i++) {
                                                            
                                                            // operations with a,b,c,d,e,f,g,h,m,n,o,p

                                                            variation += variationPerMatch;
                                                        }
                                                        double finalVariationMatches = variation / wrapper.list.size();
                                                        if (finalVariationMatches < wrapperMinVariation.minVariation) {
                                                            wrapperMinA.minA = a;
                                                            wrapperMinB.minB = b;
                                                            wrapperMinC.minC = c;
                                                            wrapperMinD.minD = d;
                                                            wrapperMinE.minE = e;
                                                            wrapperMinF.minF = f;
                                                            wrapperMinG.minG = g;
                                                            wrapperMinH.minH = h;
                                                            wrapperMinM.minM = m;
                                                            wrapperMinN.minN = n;
                                                            wrapperMinO.minO = o;
                                                            wrapperMinP.minP = p;
                                                            wrapperMinVariation.minVariation = finalVariationMatches;
                                                        }
                                                    });
                                                });
                                            });
                                        });
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });

标签: javamultithreadingstreamthread-safety

解决方案


问题是由相同代码提供的输出,但使用“for”循环与流替代方案提供的输出不同。

由于问题中的代码不完整,因此无法知道为什么并行化它会给出不同的答案。一种可能性是它是浮点舍入误差的结果。如果计算以不同的顺序发生,则可能导致答案以不同的方式四舍五入。

我认为流方法是不正确的,因为我所做的操作是串行的,线程的顺序是随机的,所以处理做得不太正确。

这是有道理的;看上面。


有什么方法可以获得相同的结果或并行化 for 循环?

由于我们无法理解代码应该做什么,我认为我们无法提出替代方案。(最好的答案可能是完全不同的算法方法......不涉及 5 12单独的计算。)

但是,我会注意到,parallel()在每个级别添加可能会使代码变慢而不是变快。并行运行任务会带来开销。如果任务太小(即粒度太细),创建和管理任务的开销可能会淹没通过并行化可能实现的节省。

除非您的 JVM 可以访问大量可笑的物理内核,否则将计算分解为 5 12 个可能并行的任务/步骤是一个坏主意。


推荐阅读