Aritalab:Lecture/Programming/C/Parallel
From Metabolomics.JP
Posix スレッド
Pthreads とは pthread.h ヘッダーファイルで定義される C 言語用のライブラリです。これを用いてメモリ共有型の並列プログラムを組むことができます。UNIX の gcc でコンパイルする時は gcc -pthread オプションをつけて下さい (cygwin環境ではつけなくてもコンパイル可能)。これから以下の 3 項目について解説します。
- 排他制御 (mutual exclusion または mutex と呼ばれる処理。ロックの概念)
- 条件変数(ウェイトとシグナル)
- 同期
関連サイトとしてはローレンスリバモア国立研究所のチュートリアルが秀逸です。並列プログラミング全般やOpenMPの解説もあります。まずは Java によるプログラミングの項目をみて、排他制御と条件変数の使い方を理解しておいて下さい。
スレッドの作成、排他制御
具体例をみるのが一番なので、とにかく C コードを示すようにします。まず、i番目のスレッドがそれぞれ 100i から 100*(i+1) までの数を足し算してそれらの総和を計算するプログラムをみてみます。
#include<stdio.h> #include<pthread.h> #define NTHREAD 3 /* スレッドに渡すデータはグローバル変数にする */ int global_sum[NTHREAD+1]; /* スレッドの終了を待つための id 格納場所 */ pthread_t callThd[NTHREAD]; /* グローバル変数書き込み用ロック */ pthread_mutex_t lock; int main(void); void* thread(int id, void* arg); void* thread(int id, void* arg) { int i, j, sum; sum=0; for(i=100*id; i <= 100*(id+1); i++) sum += i; pthread_mutex_lock(&lock); global_sum[id] = sum; global_sum[NTHREAD] += sum; /* グローバル変数の状態表示。ロック外に出しても良い */ printf("summing ["); for(j=0; j < NTHREAD; j++) printf("%d ", global_sum[j]); printf("] = "); printf("%d\n", global_sum[NTHREAD]); pthread_mutex_unlock(&lock); pthread_exit((void*)0); } int main(void) { long i; void *status; pthread_attr_t attr; pthread_mutex_init(&lock, NULL); pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); pthread_t tid; for(i=0; i < NTHREAD; i++) pthread_create(&callThd[i], &attr, thread, (void*)i); pthread_attr_destroy(&attr); for(i=0; i < NTHREAD; i++) pthread_join(callThd[i], &status); pthread_mutex_destroy(&lock); pthread_exit(NULL); }