(ソースコードメモ)GCCでのOpenMP/OpenACC実装を見てみる
1. はじめに
OpenMPおよびOpenACCは、CやFortranでディレクティブ(指示文)により、コンパイラに対して並列化を指示するものである。例えば、OpenMPの場合、以下のように#pragma omp parallel
という指示文で指示する。これにより、明示的にマルチスレッドプログラミングをしなくても、コンパイラ側で処理が行われる。OpenACCの場合は、他デバイスの処理コード生成(NVIDIA GPUやAMD GPU等)が行われる。
#pragma omp parallel
{
body;
}
2. OpenMP/OpenACCの処理
OpenMP/OpenACCのディレクティブ(指示文)の処理は、フロントエンドだけでなく、GIMPLEのパス上でも行われている。そして、最終的にビルドイン関数を含んだライブラリを介して実行する。項目として示すと以下通りである。
- ディレクティブを検出しビルトイン関数に置き換える処理(コンパイラ)
- GCCのビルドイン関数(例:
GOMP_parallel
)として処理するlibgompに分かれる。(ランタイム)
2.1. GCCでのコンパイル
コンパイルパス
コンパイラの中では、パーサの後、パス上でOpenMP/OpenACCの処理が行われている。
まず、パーサーは、C言語の場合、c/c-parser.c
、C++言語の場合、cpp/parser.c
である。(余談:githubのコードは、1MBを超えると行指定しずらいのでコードのみリンクを張っている。)
その後、gimple形式での最適化を行う。ここでpass_xxxx
が、gimpleの最適化関数である。関連するパス上の関数を上げると以下のとおりである。
- gimplify.c:omp_notice_variable
- gimplify.c:gimplify_expr
- pass_diagnose_omp_blocks
- pass_expand_omp
ここで、組み込み関数(builtin function)は以下で定義されている。
組み込み関数(builtin)関数の生成
コンパイル時は、pass_omp_expand
処理の延長で、BUILT_IN_GOMP_PARALLEL
等の組み込み(builtin)関数の出力を行う。そして、DEF_GOMP_BUILTIN
マクロでlibgompの関数であるGOMP_parallel
等へのマッピングを行う。
関連しているコードは以下である。
2.2. OpenMPのランタイム(libgomp)
libgomp側
組み込み(builtin)関数の実体が、libgompにある。例えば、GOMP_parallel
等が定義されている。また、libgompは、環境変数により、OpenMPのスケジューリングを設定できる。このため、libgomp内には、parse_scheduleや、gomp_schedule_type等の関数がある。
ここでは、GOMP_parallel
関数を見ていく。同関数では、gomp_team_start
を呼び出して、スレッドを生成する。そして、中では、gomp_thread_start_data
構造体で、スレッドを管理する。最終的に、GOMP_parallel_end
関数およびその先の、gomp_team_end
関数で同期して終了する。
void
GOMP_parallel (void (*fn) (void *), void *data, unsigned num_threads,
unsigned int flags)
{
num_threads = gomp_resolve_num_threads (num_threads, 0);
gomp_team_start (fn, data, num_threads, flags, gomp_new_team (num_threads),
NULL);
fn (data);
ialias_call (GOMP_parallel_end) ();
}
関連ソースコードは、主に以下のファイルである。
-
libgomp/
- libgomp.h
- parallel.c GOMP_xxxxx 等の関数
- team.c gomp_team_xxx等の関数
A. 参考資料
A.1. 概要
- OpenMPとOpenACCの違い
-
独自CPU開発で学ぶコンピュータのしくみ
- GCCやBinutilsの新アーキへの移植概要を知るには良い本である。
A.2. GCC
-
Openmp and automatic parallelization in gcc (2006)
- GCC 4.2の段階では、ICC9.0(Intel)より、SPEC OMP2001のベンチマークが1%程度早い。
- Prototyping the automatic generation of MPI code from OpenMP programs in GCC(2008)
A.3. libgomp
A.4. OpenMP
A.5. OpenACC
- Speeding up Programs with OpenACC in GCC(2019/02)
-
Improving GCC’s Performance on OpenACC Applications(2018/03)
- OpenACCのGCC改造版の紹介
A.6. gccのコンパイル手順
- GCCやBinutilsの新アーキへの移植概要を知るには良い本である。
- GCC 4.2の段階では、ICC9.0(Intel)より、SPEC OMP2001のベンチマークが1%程度早い。
- OpenACCのGCC改造版の紹介
ubuntu 19.10でのgcc9.xのコンパイル手順は、以下のとおりである。なお、make
で並列化オプション(-j
)をつけないと非常に遅くなる。ここでは、8コアでコンパイルしているので8を入れている。5分程度かかる。一方このオプションを外すと20分以上かかる。
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install gcc
$ sudo apt install make
$ sudo apt install build-essential
$ sudo apt install flex
$ git clone https://github.com/gcc-mirror/gcc/
$ cd gcc
$ git checkout releases/gcc-9.3.0
$ ./contrib/download_prerequisites
$ mkdir build && cd build
$ ../configure --enable-languages=c,c++ --prefix=/usr/local --disable-bootstrap --disable-multilib
$ make
$ make install
$ /usr/local/bin/gcc -v
$ /usr/local/bin/g++ -v
この手順は、gccのmaster(c5bac7d127f288fd2f8a1f15c3f30da5903141c6)(2020/04/18)に対して行ったが、コンパイルできた。
参考資料
A.7. GCCのコンパイルパス
gimpleレベルでの最適化を行うコンパイルパスは、以下の通りである。コンパイルパスは、passes.defで定義されている。
- pass_diagnose_omp_blocks
- pass_lower_omp
- pass_expand_omp
- pass_simd_clone
- pass_ipa_oacc
- pass_ipa_oacc_kernels
- pass_oacc_kernels
- pass_expand_omp_ssa
- pass_oacc_device_lower
- pass_omp_device_lower
- pass_omp_target_link
openmpに関するソースコードは以下の通りである。
参考文献
Author And Source
この問題について((ソースコードメモ)GCCでのOpenMP/OpenACC実装を見てみる), 我々は、より多くの情報をここで見つけました https://qiita.com/sakaia/items/97e332db0c865f3c84a8著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .