スレッドとは
端的に言うと、スレッドとは、プログラムを実行する主体の最小単位です。ここで言っている主体とは、例えば、a.outという実行ファイルを実行する"そのもの"を指します。プログラムを実行するスレッドが1つであればそれをシングルスレッドプログラムと呼び、プログラムを実行するスレッドが複数であればそれをマルチスレッドプログラムと呼びます。シングルスレッドプログラムはa.outを逐次実行し、マルチスレッドプログラムはa.outを並列・並行実行します。次にリソースの観点では、スレッドはプログラムカウンタを始めとしたレジスタ群とスタックを個別に持ちます。スレッドは、プログラムを実行する主体の最小単位であるため、それぞれに個別のプログラムカウンタとスタックを持つ必要があります。一方で、命令コードと静的データ、ヒープは、スレッド間で共有されます。これら命令コード、静的データ、ヒープを所有する主体となるのが、プロセスです。
スレッドは、必ず1つのプロセスに属します。また、1つのスレッドが2つ以上のプロセスに属することはありません。プロセスというのは、実行される実行ファイルごとのメモリ上の区切りのようなものです。プロセスごとに、命令コード、静的データ、ヒープ、スタックをメモリ上に持ちます。実行ファイルa.outを2つ同時に実行すれば、2つのプロセスがコンピュータ上に同時に存在するということになります。もちろんこのとき、それぞれのプロセスにスレッドが存在します。
シングルスレッドプログラムとマルチスレッドプログラム
シングルスレッドプログラムとマルチスレッドプログラムの実装の違いを、簡単に見てみます。マルチスレッドプログラムで用いるスレッドライブラリは、openMPとpthreadを使いました。以下、printfを10回実行するプログラムです。環境によっては、マルチスレッドプログラムのhelloがプリントされる順番が入れ替わったりするかと思います。
singleThread.c
#include <stdio.h> int main(void) { int i; for(i = 0; i < 10; i++) { printf("hello%d\n", i); } return 0; }
multiThread_openMP.c
#include <stdio.h> #include <omp.h> int main(void) { int i; #pragma omp parallel for for(i = 0; i < 10; i++) { printf("hello%d\n", i); } return 0; }
multiThread_pthread.c
#include <stdio.h> #include <pthread.h> #define NUMOF_THREADS 10 void* printHello(void* arg) { printf("hello%d\n", *(int*)arg); } int main(void) { int i; pthread_t threads[NUMOF_THREADS]; int threadArg[NUMOF_THREADS]; for(i = 0; i < NUMOF_THREADS; i++) { threadArg[i] = i; pthread_create(&threads[i], NULL, printHello, (void*)&threadArg[i]); } for(i = 0; i < NUMOF_THREADS; i++) { pthread_join(threads[i], NULL); } return 0; }
singleThread.cは、単にprintfをfor文で回しているだけなので、特に問題ないと思います。
multiThread_openMP.cは、singleThread.cとほぼ同じです。異なるのは、openMPのヘッダをインクルードしていることと、for文の前に#pragma omp paralle forの1行があることだけです。たったこれだけで、for文のなかのprintfが並列・並行実行されます。
multiThread_pthread.cは、openMPのものと同じ並列・並行実行であるのに対して、コード量が多くなっています。これは、pthreadでは、スレッドの作成と、終了待ちを関数呼び出しで明示的に行う必要があるためです。openMPの方では、ほぼスレッドなど意識せずただfor文を並列に実行する、とプログラムしているだけでした。
上記の例を一見すると、openMPの方が簡単にマルチスレッドプログラムを作ることができます。しかし、for文の並列化はopenMPが得意とするところなので、openMPの方がコード量を少なく記述できているだけです。
世にいくつかもあるスレッドライブラリですが、それぞれに得意なところ、不得意なところがあります。得意なところは、比較的コード量が少なくなり、不得意なところはコード量が多くなるのが一般的かと思います。また、各スレッドの同期等の細かな動作を細かく制御できるスレッドライブラリは、細かく制御できる分、コード量が多めになる傾向があります。pthreadは比較的何でもできるスレッドライブラリなので、並列化のためのコード量が多めになりがちです。
0 件のコメント:
コメントを投稿