はじめに
この連載は、OpenMPを通じて並列処理の考え方をお伝えすることを目的としています。マルチコアCPUが既に普及していますので、今後は並列プログラミングが一般的なものとなり、さまざまな技術が登場するでしょう。その時、並列プログラミングの根底に流れる考え方を身に付けられていれば、比較的容易に新技術も習得することができるでしょう。
今回はOpenMPの変数に関連する事柄について解説します。正しく並列プログラミングをするためには、メモリモデルを理解する必要がありますので、丁寧にメモリモデルの解説も行います。
なお、この連載で解説に使用するサンプルコードはあくまでもOpenMPの基礎を理解するためのものであり、実務でOpenMPを使用する際にはよく理解してから用途に適したプログラミングを行ってください。
本記事の対象を超えるもの、記述箇所を特定しないもの、読者固有環境に起因するもの、読者の主義思想に関するもの、読者の誤解によるもの、社会人としてのマナーを欠いたものなどは質問/指摘を頂いてもお答えできません。あらかじめご了承ください。
対象読者
筆者が想定している読者はCの基本的文法をマスターし、並列化プログラミングに興味を持っている方です。凝ったテクニックを極力さけ、基本的な文法さえ分かれば読めるように注意しますので、並列化に興味を持っている方はぜひこの連載に目を通してください。
必要な環境
必要な環境については第1回を参照してください。
なお、この連載は基本的にWindows環境を想定して解説しますが、OpenMPそのものは他のOS上でも動作しますので、適宜読み替えて参考にしてください。
理想と現実
並列処理を簡潔に言うと、複数のCPUを有効利用する技術です。ですから、CPUが2個になれば処理効率が2倍になり、処理時間は半分になると思う方もいるでしょう。しかしながら、前回少し触れましたが、実際は処理効率が2倍になることは、ほぼありません。理論的に処理効率が2倍になることはありえますが、それはCPUのキャッシュなどがうまく働いた時のことであり、まずないと考えてよいでしょう。
前回処理効率が1.99倍以上になるサンプルを示しましたが、これはWindows OSとOpenMPの特性を利用した理想的な処理効率であり、実務的なプログラムで同様の処理効率を出すのは非常に困難です。ですから、前回も言いましたが、必ず並列処理に対応したパフォーマンスツールで測定し、推測で並列プログラミングをしないという心掛けが大事です。
ただし、だからと言ってOpenMPが役に立たないと考えるのは早計です。正しい知識を持って上手くプログラムを組めば、CPUのコア数に比例してパフォーマンスが向上するシステムが開発できます。また、深く知れば知るほど理想値に近付くことができます。 今後シングルコアのCPUが劇的なスピードアップ遂げることは考えにくいうえに、CPUのマルチコア化の流れが変わることは考えられませんので、OpenMPを学んでマルチコア時代に対応しましょう。
並列計算モデル
逐次プログラミングはメモリモデルを意識しなくてもできました。しかし、並列プログラミングをする時はメモリモデルを理解しないとバグを生み出します。そこで、今回はOpenMPのメモリモデルを解説します。
しかし、OpenMPに特化したメモリモデルをいきなり解説しても全体像が分からないと理解しづらいでしょうし、将来役に立つ知識だと思いましたので、まずは並列計算モデルについて解説します。 並列処理には次のような方式の技法があります。
技法 | 説明 |
単一命令複数データ (SIMD:Single Instruction Multiple Data) |
同質のプロセッサに複数のデータを割り当て、同一の命令を同時に行わせる方式です。 |
複数命令複数データ (MIMD:Multiple Instruction Multiple Data) |
同質または異質のプロセッサに、個別の命令とデータを割り当てて同時に処理をする方式です。 |
超長形式命令語 (VLIW:Very Long Instruction Word) |
互いに依存性がなく、同時に実行できる複数個の命令を長い命令語に詰め込んで同時に実行する方式です。 |
データフロー | 複数のプロセッサに向けて、データと制御信号が渡され、データが揃ったプロセッサは他のプロセッサとは独立に並列的に実行する方式です。 |
ストリーム | ベクトルや文字列の様な順序付けされた、一連のデータ(ストリーム)に対して行うための方式です。データに対して行った処理の結果を、メモリに返さないで、直ちに次の操作へデータを渡します。 |
パイプライン | 一つのタスクをほぼ均等に分割して、パイプ中をデータが流れて加工されていくように、流れてくるデータを順次に分割されたタスクで操作する方式です。 |
それに加えて、どのようなマルチプロセッサなのかを考慮する必要があります。マルチプロセッサには、複数のプロセッサでメモリを共有する「密結合方式」と、複数のプロセッサが独立してメモリをもつ「疎結合方式」があります。
OpenMPは共有メモリ方式(密結合方式)で、仕様書にはSPMD(single program multiple data)構文などでベース言語であるC、C++、およびFortranを拡張して指示文とすると書かれていますので、一つの命令で複数のデータを処理する方式であることが分かります。ただし、あくまでも単一プログラムだと書かれていますので、SIMDと似ているものの全く同じではないと思われます。
明言されていませんが、仕様書から筆者が推測するに、スレッドプログラム単位で複数のデータを処理するという意味なのでしょう。注意してください。