Coarray Fortranの紹介:並列化すべきか?

非常に長い間、私は、今日人気のあるプログラミング言語の「先祖」の一人がいる段階について書きたかった。 はい、Fortranについて話します。 私は多くの開発者の心の中にあるステレオタイプを破ろうとします-Fortranは将来性のない古代言語であり、他の誰もそれについて書いていないことは確かです。 それどころか、それは非常に活発に進化しており、長い間、同じC / C ++に匹敵する、標準で安置されたさまざまな機能の豊富なセットを提供してきました。

「古い」77番目のFortranの残りはあまりありません。95標準では、独自のデータ型を作成し、メモリを動的に割り当ててクリアし、ポインタを操作し、関数と演算子をオーバーロードすることができました。 実際、ツールのセットとは少し異なります。 しかし、言語を比較しようとは思いません。これは哲学の問題です。 Fortran Intelコンパイラは大きな需要があり、実際、同じC ++よりもさらに積極的に入手されていると言えます。

この投稿の目的は、現状について話すことです。 実際、今日のFortranはパラレル言語であり、Coarrayが登場したFortran 2008標準の採用により1つになりました。



だから、まず最初に。 プログラミングモデルSPMD(Single Program MultipleData)が基礎として採用されました。 MPIに精通していれば、本質は同じです。アプリケーションを作成しているので、そのコピーは特定の回数だけ並行して実行されます。 さらに、各コピーには独自のローカルデータがあります。 異なるコピーからアクセスする必要があるデータは、Coarrayと呼ばれる特別な構文を使用して記述されます。



理解するには、単純なHello Worldの例を挙げてください。



program hello write(*,*) "Hello world" end program hello
      
      







実際には、最も一般的なコード。 –coarrayキー(Intelコンパイラー)でコンパイルした直後に、プログラムのいくつかの異なるコピーから、またはCoarrayの用語で異なるImage'eys(イメージ)から「挨拶」が表示されます。 さらに、たとえば、-coarray-num-images = xスイッチまたはFOR_COARRAY_NUM_IMAGES環境変数を使用して、それらの数を制御できます。 実行が行われる方法を決定する方法があることは明らかです。 例を複雑にしてみましょう:



 program hello_image write(*,*) "Hello from image ", this_image(), "out of ", num_images()," total images“ end program hello_image
      
      







起動後、次のようなものが表示されます。



 Hello from image 1 out of 4 total images Hello from image 4 out of 4 total images Hello from image 2 out of 4 total images Hello from image 3 out of 4 total images
      
      







明らかに、アプリケーションは4回実行されました(4コピー/イメージ)。 Coarrayに関するこのデータがあれば、原則として、すでに並列アプリケーションを作成できます。



主な質問に対する答えがないので、ここは非常に愚かです-データはどうですか? このために、非常にシンプルで明確な構文が導入されています。



 real, codimension[*] :: x real :: y[*]
      
      







角括弧は、Coarrayを使用していることを示しています。

この例では、これらはプログラムのすべてのコピーでまだ利用可能な単なるスカラーです。 ただし、必要なコピー(イメージ)でこのスカラーの値を参照できるようになりました。



たとえば、y [2]と書くと、イメージ2のyの値になります。これにより、データを使用した「実際の」並列作業の可能性が広がります。



当然、Coarrayオブジェクトをポインターを介して別のオブジェクトに関連付けようとしたり、CoarrayオブジェクトをCコードに渡すなど、Coarrayには多くの論理的な制限があります。

以前に変数xをCoarrayとして宣言したことを考慮して、さらにいくつかの例を見てみましょう。



 x = 42.0
      
      







この場合、画像のローカル変数xを使用して操作しています。

コードに角かっこが表示されるとすぐに、これは変数が別のプログラムイメージでアクセスされているという事実への明示的なポインタになります。



 x[3] = 42.0 !     42   3 x = x[1] !           1 x[i] = x[j] !     I      j
      
      







Coarrayの良い点は、純粋なMPIとは異なり、メッセージの送受信を気にしないことです。 これはすべて、実装(同じMPIを既に使用している)の肩の上にあります。 しかし、これは「上」です。 さらに、コードは分散メモリを備えたシステムと共有メモリを備えたシステムの両方で機能します。 キーをcoarray = sharedまたはcoarray = distributedに変更するだけです。



プログラムのさまざまなコピーにデータがあるため、それらを同期する手段があるはずだと考えるのは論理的です。 もちろんそうです。 これは、たとえば、すべての画像を同期するSYNC ALLコンストラクトです。 SYNC IMAGES()もあり、特定の画像のみを同期できます。



別の例:



 integer, codimension[*] :: fact integer :: i, factorial fact = this_image() SYNC ALL if ( this_image() == 1 ) then factorial = 1 do i = 1, num_images() factorial = factorial * fact[i] end do write(*, *) num_images(), 'factorial is ', factorial end if
      
      







当然、これは階乗を計算する最速の方法ではありませんが、Coarrayを使用することの本質をよく示しています。



まず、ファクトをCoarrayとして宣言し、各画像で画像の番号に等しい値を割り当てます。 すべての値を乗算する前に、それらが既に割り当てられていることを確認する必要があるため、SYN​​C ALLを使用します。 そして、おそらく「マスター画像」などの番号1の画像では、階乗を計算します。



その結果、非常に効果的なツールが得られました。これは、異なるメモリ構成を持つシステム用の並列アプリケーションを作成できる言語の一部です。 当然、コンパイラーのサポートとCoarrayの実装の主な難点はパフォーマンスです。 現時点では、それはまだ最強のポイントではありません...しかし、ここにはさまざまなコンパイラの大きな展望があります。



私は、最後に採用された標準からの「新製品」に関する簡単な説明を終えています。 Fortranコードを見るのはさほど退屈ではなかったと思います。 レビューが反対を示し、このトピックに関する活発な興味を起こしたら、私はあなたに喜びを拒否し、トピックを続けません。 そして今、あなたの注意に感謝します。



All Articles