純粋な関数は、並列化を容易にすることが知られています。 本質的に並列実行に適応させる関数型プログラミングについてはどうですか?
Javacなどのコンパイラは、メソッドが純粋な関数であるかどうかを検出するのに十分スマートですか?Functionなどの機能インターフェイスを実装するクラスを常に実装できますが、副作用があります。
NullPointerException
。これに基づく最適化の利点は、通常のJavaアプリケーションではおそらくかなり小さいでしょう。
純粋な関数は、並列化を容易にすることが知られています。 本質的に並列実行に適応させる関数型プログラミングについてはどうですか?
Javacなどのコンパイラは、メソッドが純粋な関数であるかどうかを検出するのに十分スマートですか?Functionなどの機能インターフェイスを実装するクラスを常に実装できますが、副作用があります。
NullPointerException
。これに基づく最適化の利点は、通常のJavaアプリケーションではおそらくかなり小さいでしょう。
回答:
メソッドが純粋な関数であるかどうかを検出するのに十分なJavacなどのコンパイラーです。
「十分にスマート」という問題ではありません。これは純度分析とれ、一般的なケースでは不可能であることが証明されています。つまり、停止問題を解決することと同等です。
もちろん、オプティマイザーは常に不可能なことを常に実行します。「一般的なケースではおそらく不可能」とは、機能しないことを意味するのではなく、すべての場合に機能しないことを意味します。そのため、実際には関数が純粋かどうかをチェックするアルゴリズムがあります。結果が「わからない」になることはほとんどありません。つまり、安全性と正確さの理由から、仮定する必要があります。この特定の機能は不純かもしれません。
でも、それは例にない仕事を、アルゴリズムが複雑で高価です。
だから、それは 問題#1です:特別な場合にのみ機能します。
問題#2:ライブラリ。関数を純粋にするために、関数は純粋関数のみを呼び出すことができます(そして、それらの関数は純粋関数のみを呼び出すことができますなど)。Javacは明らかにJavaについてのみ知っており、見ることができるコードについてのみ知っています。したがって、関数が別のコンパイル単位で関数を呼び出す場合、それが純粋であるかどうかを知ることはできません。別の言語で書かれた関数を呼び出す場合、あなたは知ることができません。まだインストールされていないかもしれないライブラリ内の関数を呼び出す場合、あなたは知ることができません。等々。
これは、プログラム全体の分析があり、プログラム全体が同じ言語で記述されており、すべてが一度にコンパイルされる場合にのみ機能します。ライブラリを使用することはできません。
問題#3:スケジューリング。どの部分が純粋であるかを把握したら、それらを別々のスレッドにスケジュールする必要があります。か否か。スレッドの開始と停止は非常に高価です(特にJavaの場合)。スレッドプールを保持し、それらを開始または停止しない場合でも、スレッドコンテキストの切り替えは高価です。スケジュールとコンテキストの切り替えにかかる時間よりもかなり長く計算が実行されることを確認する必要があります。そうしないと、パフォーマンスが低下しますが、向上しません。
おそらく今ご想像のとおり、計算にかかる時間を計算することは一般的なケースでは不可能であることが証明されており(時間がかかるのは言うまでもなく、有限の時間がかかるかどうかもわかりません)、特別な場合。
余談:Javacと最適化。javacのほとんどの実装は、実際には多くの最適化を実行しないことに注意してください。たとえば、Oracleのjavacの実装は、最適化を行うために基礎となる実行エンジンに依存しています。これは別の問題につながります。たとえば、javacは特定の関数が純粋であり、十分に高価であると判断したため、別のスレッドで実行されるようにコンパイルします。次に、プラットフォームのオプティマイザー(HotSpot C2 JITコンパイラーなど)が登場し、関数全体を最適化します。今、あなたは何もしていない空のスレッドを持っています。または、javacが別のスレッドで関数をスケジュールすることを決定し、プラットフォームオプティマイザーが スレッドの境界を越えてインライン化を実行できないことを除いて、完全に最適化します。したがって、完全に最適化できた関数は不必要に実行されます。
したがって、このようなことは、単一のコンパイラーで最適化のほとんどを一度に行う場合にのみ意味があり、コンパイラーは、さまざまなレベルでのさまざまな最適化とそれらの相互作用を認識し、活用することができます。
たとえば、HotSpot C2 JITコンパイラーは実際には自動ベクトル化を実行しますが、これも自動並列化の一種です。
definition
、異なる使用して、definition
のはpurity
おそらく曖昧である
StringBuilder
、私はそれを却下し、単に仮定したいので、OPは、javacの書き込みを行うが、ホットスポットを意味し、)非感覚です。あなたの問題#2は、最適化に対してかなり良い理由で何のjavacでは。
賛成の答えは、一つのことに注意することに失敗しました。スレッド間の同期通信は非常に高価です。関数が1秒あたり数百万回の呼び出しの速度で実行できる場合、実際には、そのままにするのではなく、並列化するのがさらに難しくなります。
アトミック変数を使用したビジーループを使用した最速の同期スレッド間通信は、残念ながらエネルギー効率が悪いです。条件変数を使用してエネルギーを節約する必要がある場合、スレッド間通信のパフォーマンスが低下します。
そのため、コンパイラは関数が純粋であるかどうかを判断するだけでなく、関数の実行時間を推定して、並列化が最終的な成果であるかどうかを確認する必要もあります。また、アトミック変数または条件変数を使用してビジーループを選択する必要があります。そして、背中の後ろにスレッドを作成する必要があります。
スレッドを動的に作成する場合、条件変数を使用するよりもさらに遅くなります。そのため、コンパイラは、すでに実行されている一定数のスレッドをセットアップする必要があります。
したがって、あなたの質問に対する答えは「いいえ」です。コンパイラは、特にJavaの世界で純粋な関数を自動並列化するのに十分な「スマート」ではありません。それらは自動並列化しないので賢いです!