私たちはまだそこにいません。
純粋な宣言型スタイル (関数型スタイルはこのカテゴリに含まれますが、他のスタイルも含まれます) のプログラムは、すべてのデータ依存関係が明示的であるため、並列化に適している傾向があります。これにより、プログラマーは言語が提供するプリミティブを手動で使用して、データへのアクセスを共有するかどうかに関係なく、2 つの独立した計算を並行して実行するように指定することが非常に簡単になります。すべてが不変で副作用がない場合、処理の順序を変更しても結果には影響しません。
言語によって純粋性が強制されている場合(Haskell、Mercury などのように、純粋性が奨励されているが強制されていない Scala、F# などとは異なります)、コンパイラーがプログラムを自動的に並列化しようとする可能性がありますが、既存のものはありません。私が知っている言語は、デフォルトでこれを行います。言語がチェックされていない不純な操作を許可している場合、コンパイラーがプログラムを自動並列化する特定の試みが有効であることを証明するために必要な分析を行うことは通常不可能です。したがって、そのような言語が自動並列化を非常に効果的にサポートするとは思えません。
あなたが書いた疑似プログラムは、おそらく純粋な宣言型コードではないことに注意してください。let y = read-and-parse-a-number-from-console
およびlet x = get-integer-from-web-service-call
は不純な外部操作から計算さx
れy
ており、プログラムには実行順序を修正するものは何もありません。一般に、2 つの不純な操作をいずれかの順序で実行すると異なる結果が生じる可能性があり、これら 2 つの操作を異なるスレッドで実行すると、実行順序の制御が失われます。したがって、そのような言語がプログラムを自動並列化する場合、ほぼ確実に恐ろしい同時実行バグが発生するか、大幅な並列化を拒否することになります。
ただし、関数型のスタイルにより、そのようなプログラムを手動で簡単に並列化できます。人間のプログラマーは、コンソールとネットワークからどちらの順序で読み取るかは、ほぼ確実に問題ではないと言うことができます。共有された変更可能な状態がないことを知っていると、実装を掘り下げることなく、これら 2 つの操作を並行して実行することを決定できます (これは、変更可能な共有状態が存在するように見えなくても、命令型アルゴリズムで行う必要があります)。インターフェイス)。
しかし、強制純粋言語の自動並列化コンパイラーの邪魔になる大きな複雑さは、どの程度の並列化を行うべきかを知ることです。可能なすべての計算を並行して実行すると、新しいスレッドを生成するためのすべての起動コスト (コンテキスト スイッチは言うまでもありません) が発生する可能性があり、可能な限りの利益を大幅に圧倒します。コンパイラは、かなり大きな計算の "チャンク" をはるかに少ない数で識別し、各チャンクのサブ計算を順番に実行しながら、チャンクを並列で実行する必要があります。
しかし、「恥ずかしいほど並列な」プログラムだけが、非常に大きな完全に独立した計算にうまく分解されます。ほとんどのプログラムは、はるかに相互依存しています。したがって、手動で並列化するのが非常に簡単なプログラムのみを自動並列化できるようにしたい場合を除き、自動並列化では、相互に部分的に依存し、待機させる「チャンク」を識別して並列実行できる必要があります。別の「チャンク」によって計算されるはずの結果が本当に必要なポイントに到達したとき。これにより、スレッド間の同期の余分なオーバーヘッドが発生するため、何を並行して実行するかを選択するロジックは、すべてを順番に実行するという単純な戦略を打ち負かすために、さらに優れたものにする必要があります。
Mercury (純粋な論理プログラミング言語) の開発者は、静的分析からプロファイリング データの使用まで、これらの問題に取り組むためのさまざまな方法に取り組んでいます。興味があれば、彼らの研究論文にはさらに多くの情報があります。他の研究が他の言語でこの分野に取り組んでいると思いますが、他のプロジェクトについてはあまり知りません。