2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

(ソースコードメモ)GCCでのOpenMP/OpenACC実装を見てみる

Last updated at Posted at 2020-04-18

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の最適化関数である。関連するパス上の関数を上げると以下のとおりである。

ここで、組み込み関数(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) ();
}

関連ソースコードは、主に以下のファイルである。

A. 参考資料

A.1. 概要

A.2. GCC

A.3. libgomp

A.4. OpenMP

A.5. OpenACC

A.6. 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で定義されている。

openmpに関するソースコードは以下の通りである。

参考文献

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?