java - JVM 是否具有检测并行化机会的能力?

标签 java multithreading parallel-processing jvm

Java Hotspot 可以很好的优化顺序代码。但我在猜测,随着多核计算机的出现,运行时的信息是否可用于检测在运行时并行化代码的机会,例如检测软件流水线在循环中是否可能以及类似的事情。

有没有关于这个主题的有趣的工作?还是研究失败或一些很难解决的问题?

最佳答案

我认为 Java memory model 的当前保证使得在编译器或 VM 级别做很多(如果有的话)自动并行化非常困难。 Java 语言没有语义来保证任何数据结构实际上是不可变的,或者任何特定的语句都是纯净的且没有副作用,因此编译器必须自动计算出这些以便并行化。一些基 native 会可能会在编译器中推断出来,但一般情况将留给运行时,因为动态加载和绑定(bind)可能会引入在编译时不存在的新突变。

考虑以下代码:

for (int i = 0; i < array.length; i++) {
    array[i] = expensiveComputation(array[i]);
}

如果 expensiveComputation 是一个 pure function,并行化将是微不足道的,它的输出仅取决于它的参数,如果我们能保证 array 在循环期间不会改变(实际上我们正在改变它,设置 array[i]=.. .,但在这种特殊情况下,总是首先调用 expensiveComputation(array[i]),所以这里没问题 - 假设 array 是本地的,而不是从中引用的其他任何地方)。

此外,如果我们像这样改变循环:

for (int i = 0; i < array.length; i++) {
    array[i] = expensiveComputation(array, i);
    // expensiveComputation has the whole array at its disposal!
    // It could read or write values anywhere in it!
}

那么即使 expensiveComputation 是纯粹的并且不改变它的参数,并行化也不再是微不足道的,因为并行线程改变 的内容array 而其他人正在阅读它!并行器必须确定 哪些部分 在各种条件下 expensiveComputation 指的是数组,并相应地进行同步。

也许检测所有可能发生的突变和副作用并在并行化时将其考虑在内并非完全不可能,但非常> 很难,当然,在实践中可能不可行。这就是为什么并行化,并弄清楚一切仍然正常工作,是 Java 程序员头疼的问题。

函数式语言(例如 JVM 上的 Clojure)是该主题的热门答案。纯粹的、无副作用的功能以及 persistent (“有效不可变”)数据结构可能允许隐式或几乎隐式并行化。让我们将数组的每个元素加倍:

(map #(* 2 %) [1 2 3 4 5])
(pmap #(* 2 %) [1 2 3 4 5])  ; The same thing, done in parallel.

这是透明的,因为有两点:

  1. #(* 2 %) 函数是纯粹的:它接受一个值并给出一个值,仅此而已。它不会改变任何东西,它的输出仅取决于它的参数。
  2. vector [1 2 3 4 5] 是不可变的:无论是谁在什么时候查看它,它都是一样的。

可以在 Java 中创建纯函数,但 2) 不变性是此处的致命弱点。 Java 中没有不可变的数组。 老实说,没有什么 在 Java 中是不可变的,因为即使 final 字段也可以使用反射更改。因此,无法保证计算的输出(或输入!)不会被并行化改变 -> 因此自动并行化通常是不可行的。

由于不变性,愚蠢的“加倍元素”示例扩展到任意复杂的处理:

(defn expensivefunction [v x]
  (/ (reduce * v) x))


(let [v [1 2 3 4 5]]
  (map (partial expensivefunction v) v)) ; pmap would work equally well here!

关于java - JVM 是否具有检测并行化机会的能力?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10929184/

相关文章:

python - 在 python : child processes going defunct while others are not, 中不确定为什么

c++ - parallel_invoke 待定中的相同方法

java - 如何捕捉,为什么请求没有在 Spring Web 中映射?

java - AT-Sign 版本 :perform 上的主机名

java - Spring MVC Controller 中重定向到父窗口

java - 如何在扩展 JPanel 的类中创建 bufferstrategy

c# - 并发流图

java - Android 上的简单 MVVM 架构以及 Java 上的 AndroidX

windows - 任何显示运行线程详细信息的 Windows 工具?

c - Windows在默认线程池中设置最大线程数