OpenMPでのアトミックな処理
提供: C言語入門
2016年1月20日 (水) 19:06時点におけるDaemon (トーク | 投稿記録)による版 (ページの作成:「並列プログラミングでは、<u>処理を'''アトミック'''に行わないといけない場合があります</u>。クリティカルリージョン、クリ...」)
スポンサーリンク
並列プログラミングでは、処理をアトミックに行わないといけない場合があります。クリティカルリージョン、クリティカルセクションと呼ばれるものです。大抵は、ロックをすることで実現されます。
読み方
- atomic
- あとみっく
目次
概要
プログラムを並列化すると困るのが、共有される変数へのアクセスです。
スレッドが1つしか存在しない場合には、そのスレッドしか、リソースにアクセスしないので、問題は起きません。
しかし、スレッドが2つ以上になり、リソースをスレッド間で共有しはじめたときに、問題は発生します。
プログラムが以下の処理を行うときに、複数のスレッドが同じ処理を行うと、どうなるでしょうか?
- データの読み出し
- データの加工
- データの保存
2つのスレッドが以下のように動作すれば、問題はありません。
thread 1 データの読み出し データの加工 データの保存 thread 2 データの読み出し データの加工 データの保存
しかし、以下のように、スレッドが同時に動いている場合、データへのアクセスが競合状態(レースコンディション)に陥っています。
thread 1 thread 2 データの読み出し データの読み出し データの加工 データの加工 データの保存 データの保存
行業状態を避けるために、クリティカルリージョン(クリティカルセクション)をアトミックに処理するために、ロックを利用します。
OpenMP でのアトミックな処理
OpenMP では、 プラグマディレクティブ を用いて、プログラムをアトミックに処理することができます。
#pragma omp atomic
を記述するだけで処理はアトミックになります。
以下にシンプルな例を示します。
int i = 0; { #pragma omp atomic i++; printf ("i=%d\n", i); }
atomic を用いたシンプルな例
ソースコード atomic2.c
/* * atomic1.c * Copyright (C) 2016 kaoru <kaoru@localhost> */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int i = 0; { #pragma omp atomic i++; printf ("i=%d\n", i); } exit(EXIT_SUCCESS); }
コンパイル
$ gcc5 -std=c11 -Wl,-rpath=/usr/local/lib/gcc5/ \ -fopnemp atomic2.c -o atomic2
実行例
% ./atomic2 i=1
アセンブリ言語レベルでのコード
プラグマディレクティブを用いた場合と、そうではない場合を比較してみましょう。 gcc(gcc5)コンパイラを用いて、 -fopenmp なし、と -fopenmp あり の場合に出力されるアセンブリ言語のコードを確認しました。
以下は、atomic なし の場合です。
addl $1, -4(%rbp)
以下は、atomic あり の場合です。
lock addl $1, -4(%rbp)
アセンブリ言語のレベルでは、 lock が指定されていることがわかります。
並列化したプログラムのアトミックを用いた例
ソースコード atomic1.c
/* * atomic1.c * Copyright (C) 2016 kaoru <kaoru@localhost> */ #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { int i = 0; #pragma omp parallel { #pragma omp atomic i++; printf ("i=%d\n", i); } exit(EXIT_SUCCESS); }
コンパイル
$ gcc5 -std=c11 -Wl,-rpath=/usr/local/lib/gcc5/ \ -fopnemp atomic1.c -o atomic1
実行例
% ./atomic1 i=1 i=2
クリティカルセクションとアトミックオペレーションの違い
OpenMPには、
- atomic
- critical
が存在します。
クリティカルセクション
- ブロックのコードの直列化(serialization)を保証します。
- name タグを利用して、ブロックのグループを直列化できます。
- スピードが遅いです。
アトミックオペレーション
- スピードが速いです。
- 特別なオペレーションの直列化だけを保証します。
関連項目
ツイート
スポンサーリンク