「OpenMPでのアトミックな処理」の版間の差分
提供: C言語入門
(ページの作成:「並列プログラミングでは、<u>処理を'''アトミック'''に行わないといけない場合があります</u>。クリティカルリージョン、クリ...」) |
|||
行1: | 行1: | ||
− | 並列プログラミングでは、<u>処理を'''アトミック'''に行わないといけない場合があります</u>。クリティカルリージョン、クリティカルセクションと呼ばれるものです。大抵は、ロックをすることで実現されます。 | + | 並列プログラミングでは、<u>処理を'''[[アトミック]]'''に行わないといけない場合があります</u>。クリティカルリージョン、クリティカルセクションと呼ばれるものです。大抵は、ロックをすることで実現されます。 |
'''読み方''' | '''読み方''' | ||
+ | ;[[アトミック]]:あとみっく | ||
;atomic:あとみっく | ;atomic:あとみっく | ||
__TOC__ | __TOC__ | ||
行36: | 行37: | ||
データの保存 | データの保存 | ||
− | 行業状態を避けるために、クリティカルリージョン(クリティカルセクション) | + | 行業状態を避けるために、クリティカルリージョン(クリティカルセクション)を[[アトミック]]に処理するために、ロックを利用します。 |
== OpenMP でのアトミックな処理 == | == OpenMP でのアトミックな処理 == | ||
− | [[OpenMP]] では、 '''プラグマディレクティブ''' | + | [[OpenMP]] では、 '''プラグマディレクティブ''' を用いて、プログラムを[[アトミック]]に処理することができます。 |
<syntaxhighlight lang="c"> | <syntaxhighlight lang="c"> | ||
#pragma omp atomic | #pragma omp atomic | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | + | を記述するだけで処理は[[アトミック]]になります。 | |
以下にシンプルな例を示します。 | 以下にシンプルな例を示します。 | ||
行148: | 行149: | ||
* 特別なオペレーションの直列化だけを保証します。 | * 特別なオペレーションの直列化だけを保証します。 | ||
== 関連項目 == | == 関連項目 == | ||
+ | * [[アトミック]] | ||
* [[OpenMP]] | * [[OpenMP]] | ||
<!-- vim: filetype=mediawiki | <!-- vim: filetype=mediawiki | ||
--> | --> |
2016年2月13日 (土) 17:51時点における最新版
並列プログラミングでは、処理をアトミックに行わないといけない場合があります。クリティカルリージョン、クリティカルセクションと呼ばれるものです。大抵は、ロックをすることで実現されます。
読み方
- アトミック
- あとみっく
- 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 タグを利用して、ブロックのグループを直列化できます。
- スピードが遅いです。
アトミックオペレーション
- スピードが速いです。
- 特別なオペレーションの直列化だけを保証します。