【问题标题】:In what application niche is parallelStream from Java useful?Java中的parallelStream在哪些应用领域有用?
【发布时间】:2020-07-03 13:51:16
【问题描述】:

我正在尝试确定可以从使用 Java 8 中引入的 parallelStream API 中受益的一类 Java 应用程序。

我知道其他 SO 帖子中描述的 API 的许多警告:

  • 共享分叉/加入池,具有重要的开始时间,以及池中争用的一些潜在问题
  • 以一种在服务器(已经有多任务策略)上使用这种代码的方式不受控制地使用系统资源实际上可能是个坏主意
  • ...还有其他主要与性能有关的批评

不过,如果 Stream API 已经使用,API 提供了使用现代多核机器的代码,这些代码不是很侵入性,因此无需麻烦的多线程,开发成本低。因此,我仍然认为它在某些情况下会很有用。

我认为应用程序上下文必须是这样的:

  1. 我的申请目前是连续的
  2. 存在响应时间问题,例如挂钟时间。用户单击了 GUI 按钮并等待回复
  3. 应用程序在客户端计算机上运行,​​大多数时候我们可以期望有一些可用的 CPU 内核,而不是在已经争用资源的服务器上
  4. 我的开发团队没有人力/技能来开发自己的任务分配/线程机制,所以除非他们可以使用此 API 轻松完成,否则他们不会追求并行性

我在 github 上搜索,但很难找到非练习或教科书示例的并行流使用相关示例(我欢迎链接到 API 的中型+项目中的一些用法)。

那么 Java 语言开发人员使用此 API 的目标是哪些类型的应用程序?

您是否同意上述关于 API 有用的应用程序上下文的要求?

【问题讨论】:

  • 您是否阅读过 Effective Java 第 3 版第 48 条“使流并行时要小心”?这提出了一些建议。
  • 谢谢,这当然是相关的,但它谈到了哪些数据结构和算法可以加速。我更想找到与 API 相关的应用程序上下文。我有点假设代码中会有一些迭代,因为响应时间(第 2 项)是相关的,如何引入并行 API(选择 ArrayList...)的问题并不是我要问的.
  • @jaco0646 谢谢,是的,这个链接更接近我正在寻找的答案。您可以考虑将其格式化为答案,因为除非出现其他答案,否则我会给它赏金。

标签: java multithreading parallel-processing java-stream


【解决方案1】:

这看起来很好地解释了地点和原因的案例。 https://computing.llnl.gov/tutorials/parallel_comp/#WhyUse 我个人在以用户为中心的 Web 应用程序中没有看到有趣的案例。

fork/join 框架是一个非常酷的低级 API。许多其他更高级别的框架非常成功地使用它。我用它来生成测试数据。缓存引导。数据处理等... 在许多情况下,您可以在其他情况下获得非常好的性能提升,这只是不必要的开销。

【讨论】:

  • 虽然这是一个真正很好的并行资源,但我的问题集中在 Java parallelStream API,它是实现并行的一种方式,但在特定的上下文中。例如这个页面提到了很多大数据项目,通常你已经构建了特定的程序来有效地利用你的硬件基础设施,或者科学计算,其中类似地利用并行性是游戏的一部分。可以说,这些示例中的大多数因此不符合标准 3 和 4,并且不符合使用 parallelStream API 的条件。
  • Coursera 上有一门非常不错的莱斯大学免费课程:coursera.org/lecture/parallel-programming-in-java/… 它侧重于 Java 并行处理以及 Computation Graphs、Work、Span 等背后的理论。绝对值得学习看看。
【解决方案2】:

Should I always use a parallel stream when possible? 中提出了类似的问题。注意第二个答案是由参与 Stream API 设计的 Oracle 的 Java 语言架构师 Brian Goetz 给出的,因此他的回答可能被认为是权威的。

热门答案很快指出,并行流包括协调所需的额外开销,因此只会在每个流的单独处理量足够显着以致并行处理的收益克服初始开销的情况下提高性能。

毫不奇怪,与任何性能问题一样,建议是衡量而不是猜测。从顺序流开始,如果您有大量元素,每个元素都需要复杂的计算,请测量切换到并行流的性能差异。

附加指南(例如 OP 中列出的指南)可能会有所帮助;但众所周知,人们不擅长识别性能瓶颈,因此任何指导方针最终都可能在实际测量时失败。

【讨论】:

    【解决方案3】:

    应用程序在客户端机器上运行,大多数时候我们可以期望有一些可用的 CPU 内核,而不是在资源已经争用的服务器上

    这个预测没有任何根据。在台式机和服务器计算机上,可能只有您的应用程序正在运行,也可能有 1,000 个应用程序在运行。

    不存在并行流有用的“应用领域”。 仅当您通过定量或定性测量确保性能得到改进且它们的缺点无关紧要时,才应使用它们。

    只有在您了解下面的概念时,它们才会变得简单。它们只能应用于特定的问题子集。

    只有在以下情况下我才会考虑使用它们:

    • 所有流操作都是纯函数,因此不需要同步
    • 性能并不重要,但提升会很大(因此可以容忍共享池的争用)

    【讨论】:

    • 感谢您的深思熟虑的回答,也许没有“利基”,但我认为有“反利基”,就像它在 Web 服务器代码中可能适得其反。也许换个说法,假设你有一个工具可以自动将并行流添加到代码中,谁是潜在的最终用户,他们可以开发什么样的应用程序(利基)?
    【解决方案4】:

    根据我的经验,我使用 parallelStream 来分解必须调用一千次但每个输出都不会相互影响的函数。

    这是我回答stackoverflow问题的示例代码。 所以需要调用一个函数来根据csv行测量ecludian点

    public class Euclidian {
    
        public Double[] euclidian(Double[][] data) {
    
            Double[] result = new Double[data.length - 1];
            for (int i = 0; i < result.length; i++) {
                result[i] =
                        Math.pow(data[i][0] - data[data.length - 1][0], 2) +
                                Math.pow(data[i][1] - data[data.length - 1][1], 2);
            }
    
            return result;
        }
    }
    

    因为 csv 上的每一行都必须基于 order 计算,但每个输出都不必连接,除非数据是根据 order 在输出处获取的,所以我使用 parallelStream 对其进行了增强

    IntStream
    .range(1, data.length - 1)
    .parallel()
    .forEach(i -> {
        add(euclidian.euclidian(Arrays.copyOf(data, i + 1)), i);
    });
    

    据此,我已经针对 1049 行 csv 文件进行了测试。 将parallelStream方法与使用循环的原始代码进行比较时,结果呈指数级增长(输入csv越大,速度越快)

            for (int i = 0; i < distanceTable.length - 1; ++i) {
                distanceTable[i] = new Double[i + 1];
                for (int j = 0; j <= i; ++j) {
                    double distance = 0.0;
                    for (int k = 0; k < DataSet[i + 1].length; ++k) {
                        double difference = Double.parseDouble(DataSet[j][k]) - Double.parseDouble(DataSet[i + 1][k]);
                        distance += difference * difference;
                    }
                    distanceTable[i][j] = distance;
                }
            }
    

    您可以查看我的git project

    【讨论】:

    • 这只是一个使用示例,并没有真正回答问题。 Effective Java 第 3 版第 48 条的文本,“在使流并行时要小心”在同一方向上是一个更完整的答案,但它也不是我想要的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多