質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

並列処理

複数の計算が同時に実行される手法

Q&A

解決済

1回答

2203閲覧

OpenMPによる並列化処理について

atnet

総合スコア13

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

並列処理

複数の計算が同時に実行される手法

0グッド

1クリップ

投稿2017/10/19 08:35

編集2017/10/19 09:06

OpenMPによる並列化処理について質問させてください。

今開発をしているプログラムに、OpenMPによる並列化処理を組み込みたいと考えております。
まずはOpenMPによる並列処理がどのようなものなのか試してみようと、適当なコードをかいて実行してみたのですが、実行時間が縮まるどころかむしろ大きく伸びてしまいました。理由が何なのか自分では見当が付きません。

実行時間が縮まらない原因としてどのような要因が考えられるか、皆様の意見をお聞かせください。

実行環境
OS:Linux version 4.4.52-2vl6
コンパイラ:gcc version 4.9.3
CPU:Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz

C

1#include<stdio.h> 2#include<time.h> 3 4double X[100][100],T[100000]; 5 6int main(void){ 7 8 int i,j,k,t; 9 double tp,tnp,rate; 10 clock_t start,stop; 11 12 t = 100; 13 //並列化しなかった場合 14 for(k=0;k<t;k++){ 15 start = clock(); 16 //適当な処理 17 for(j=0;j<100;j++){ 18 for(i=0;i<100;i++){ 19 X[i][j] = (i+j)-i*j; 20 } 21 } 22 //適当な処理 23 stop = clock(); 24 T[k]= stop-start; 25 } 26 //t回の平均をとる 27 for(k=0;k<t;k++){ 28 tnp += T[k]; 29 } 30 tnp /= t; 31 //t回の平均をとる 32 //並列化しなかった場合 33 34 //並列化した場合 35 for(k=0;k<t;k++){ 36 start = clock(); 37 //適当な処理 38 #pragma omp parallel 39 { 40 #pragma omp for 41 for(j=0;j<100;j++){ 42 for(i=0;i<100;i++){ 43 X[i][j] = (i+j)-i*j; 44 } 45 } 46 } 47 //適当な処理 48 stop = clock(); 49 T[k]= stop-start; 50 } 51 //t回の平均をとる 52 for(k=0;k<t;k++){ 53 tp += T[k]; 54 } 55 tp /= t; 56 //t回の平均をとる 57 //並列化した場合 58 59 rate = tp/tnp; 60 printf("not paralleled time = %f\n",tnp); 61 printf("paralleled time = %f\n",tp); 62 printf("rate = %f\n",rate); 63 64 return 0; 65}

コンパイル時のオプションを、-fopenmp とした場合、出力は以下のようでした。

not paralleled time = 70.170000
paralleled time = 690.490000
rate = 9.840245

また、コンパイル時にオプションをつけなかった場合、出力は以下のようでした。

not paralleled time = 80.800000
paralleled time = 39.160000
rate = 0.484653

(コンパイル時のオプションを、-fopenmp となかった場合、並列化処理の効果が出ているように思えるのですが、参考にしたサイトには「オプションを-fopenmp としなかった場合OpenMPによる並列化処理は行われない」とあり、そこでも悩んでいます。)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

小さな問題が2つと、根本的な問題が1つあります。


根本的な問題:

まずはOpenMPによる並列処理がどのようなものなのか試してみようと、適当なコードをかいて実行してみたのですが、実行時間が縮まるどころかむしろ大きく伸びてしまいました。

並列処理は魔法ではありません。このようにマイロベンチマーク計測用の軽いタスクを並列処理しても、「並列化により得られる削減効果」よりも「並列化オーバヘッド による追加処理」が上回ってしまい、結果として「並列処理を行なったのに却って遅くなった」という事象に直面します。

OpenMPに限らず、どのような並列処理技術をもってしても並列化オーバーヘッドは必ず存在します。並列処理の効果を測定するには、あなたのプログラムが 実際に行う(もしくは処理負荷が近い) 計算処理タスクを対象とすべきです。


小さな問題2つ:

また、コンパイル時にオプションをつけなかった場合、出力は以下のようでした。
(コンパイル時のオプションを、-fopenmp となかった場合、並列化処理の効果が出ているように思えるのですが、参考にしたサイトには「オプションを-fopenmp としなかった場合OpenMPによる並列化処理は行われない」とあり、そこでも悩んでいます。)

コンパイル時オプション -fopenmp を指定しなければ、あなたの期待通り OpenMPは無効化されます。つまり1回目と2回目の計測対象コードはいずれも逐次処理されます。

それでも結果が異なるように見えるのは、初回(〜数回目)の試行だけメモリアクセスが遅くなるためと考えられます。実際にT[k]の値を確認してみてください。一般に、複数回の計測を行うベンチマークでは「ウォームアップ(Warm-up)」が必要になります。これは近代的なコンピュータが持つメモリキャッシュ機構によるもので、同じメモリアクセスでも1回目と2回目以降のアクセス速度が異なる結果になることがよくあります。

c

1#pragma omp for 2for(j=0;j<100;j++){ 3 for(i=0;i<100;i++){ 4 X[i][j] = (i+j)-i*j; 5 } 6}

上記のコード片は変数iに関してデータ競合(data race)を引き起こすため、並列処理としては壊れています。OpenMPデフォルトでは変数を共有(shared)するため、ループカウンタ変数iが(変数jに関する)並列処理スレッド間で共有されてしまい、それぞれのスレッドで正しい処理が行われなくなります。

並列処理を正しく記述するのは非常に難しい(慣れていても間違う)ため、逐次処理結果と並列処理結果が同じになっているか、必ず確認することを強くおすすめします。

修正案1:

c

1#pragma omp for private(i) 2 // private節を明示 3for(j=0;j<100;j++){ 4 for(i=0;i<100;i++){ 5 X[i][j] = (i+j)-i*j; 6 } 7}

修正案2:

#pragma omp for for(j=0;j<100;j++){ int i; // ブロックスコープで変数宣言 for(i=0;i<100;i++){ X[i][j] = (i+j)-i*j; } }

投稿2017/10/21 05:44

yohhoy

総合スコア6191

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

atnet

2017/10/22 11:27

非常にわかりやすい回答ありがとうございます。 yohhoy様の回答を元に自分でもいろいろ勉強することができ、並列処理の仕組みやメモリキャッシュ機構の仕組みについて、簡単にですが理解することができました。 ベンチマークの結果も当初期待していたような値になりました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問