• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:並列処理についてですが、 )

並列処理についての質問

このQ&Aのポイント
  • 並列処理の性能についての質問です。
  • スレッド切り替えとは何かについて教えてください。
  • ひとつのプロセスがすべてのコアを占有するスレッドとはどういうことですか?

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

http://oshiete1.goo.ne.jp/qa5587724.html ではどうもです。  スレッドは当初、CPUのクロックが速過ぎてメモリが追いつかないためにwaitを沢山いれて動いていました。waitはその名のとおり、待つだけで何もしていません。それではもったいないと、その空いた時間を裏で行う方法を取り入れました。それが threadです。Intelでは30186(50MHz)当たりからwaitの比重が大きくなって来たと記憶しています。  現在はそれがパソコンの主流ですが、Mac OSXではコアの負荷状態を目視できるアクティビティモニタがあるため、すべてのコアを占有するところを確認することができます。↑の「#define THREAD_NUM 3」を1~4に変えてモニタを見ながら実験してみるとthreadの特性を知ることができます(琉球大学、九州大学、京都産業大学、電気通信大学、東京大学の学生の方は学内で実験できる環境にあります)。  同じことがプロセスの並列起動、並列処理を行わせることで実現できます。巷ではセマフォやミューテックスが必須であって、有り得ない話と思われていますが、それはデマです。これも目て確認してみてください。一応、threadを使わないオーソドックスな並列プロセスとした dual coreの場合の事例(2台並べたと同じ環境)を上げておきます。起動は「 ./a.out 」です。 www.xfile09.com/fig/algo1.pdf /* Main program by Mac OSX * file name: xxx.c * compile: gcc xxx.c * execution: ./a.out */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/stat.h> #include <signal.h> #include <errno.h> #include "xxx3.h" #define CODE 999 /* 適当に変更のこと */ void pi_calc(double *); void handler(int); int main(void) { int shmid; void *shmaddr; char command_line[64]; double pi; struct timeval tv; struct timezone tz; double before, after; /* 共有メモリの確保 */ if (((shmid = shmget(CODE, sizeof(*ptr) + 2, IPC_CREAT | S_IRUSR | S_IWUSR)) == -1) || ((shmaddr = shmat(shmid, NULL, 0)) == (char *)-1)) { perror("Shared memory set"); exit(1); } /* 共有メモリに struct構造体をあてがう */ ptr = (struct set1 *)shmaddr; /* 自身プロセスIdを記録する */ ptr->id_number[PARENT] = getpid(); /* シグナルハンドラー登録 */ signal(SIGCONT, handler); /* バックグランドで同時計算可に*/ ptr->flag[PARENT] = ON; // 子プロセス完了まで待つ sprintf(command_line, "./xxx2 %d &", shmid); if (system(command_line) != 0) { perror("Shell command line"); exit(1); } /* 子プロセスの順延に配慮 */ fprintf(stderr, "Program setting now"); while (ptr->flag[PARENT] != OFF) { fprintf(stderr, "."); sleep(1); } /* 子プロセスへ並列計算するようシグナルを送信 */ ptr->flag[PARENT] = ON; ptr->flag[CHILD] = OFF; kill(ptr->id_number[CHILD], SIGCONT); gettimeofday(&tv, &tz); before = (double)tv.tv_sec + (double)tv.tv_usec * 1.0e-6; /* 円周率の計算 */ pi_calc(&pi); // 共有メモリ:&ptr->shmem1 /* 計算終了まで待機(dead_lockの回避) * 作業継続入力後も子プロセスが出力中なら1秒休む。 * ただし出力が完了したならシグナル等で起こされる。 */ while (ptr->flag[PARENT] != OFF) sleep(1); /* データ並列によるπ = 前半部分+後半部分 */ pi = pi + ptr->shmem2; // 共有メモリ:pi=ptr->shmem1+ptr->shmem2 printf("pi= %.11f\n", pi); gettimeofday(&tv, &tz); after = (double)tv.tv_sec + (double)tv.tv_usec * 1.0e-6; fprintf(stderr, "%.3f sec\n", after - before); /* 子プロセスのプログラム終了送信 */ ptr->flag[CHILD] = ON; kill(ptr->id_number[CHILD], SIGCONT); /* 共有メモリの解除 */ if (shmdt(shmaddr) == -1 || shmctl(shmid, IPC_RMID, 0) == -1) { perror("Shared memory closed"); exit(1); } return 0; } /* 円周率の計算 */ void pi_calc(double *sum) { int i; double step, temp; step = 1.0 / (double)TIMES; *sum = 0.0; /* データ並列、前半部分を受け持つ */ for (i = 1; i <= (TIMES / DIVIDED); i++) { temp = (i - 0.5) * step; *sum += 4.0 / (1.0 + temp * temp); } *sum *= step; } /* 何もしないシグナル処理関数 */ void handler(int dummy) { ; } ----- ここまで ----- /* Other parallel processing program by Mac OSX * file name: xxx2.c * compile: gcc xxx2.c -o xxx2 * execution: Don't execute this program. */ #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/stat.h> #include <signal.h> #include <errno.h> #include "xxx3.h" void pi_calc(double *); void handler(int); int main(int argc, char *argv[]) { int shmid; void *shmaddr; /* 親プロセスから受け継ぐ */ shmid = atoi(argv[--argc]); if ((shmaddr = shmat(shmid, NULL, 0)) == (char *)-1) { perror("Shared menory set"); exit(1); } /* 共有メモリに struct構造体をあてがう */ ptr = (struct set1 *)shmaddr; /* 自身プロセスIdを記録する */ ptr->id_number[CHILD] = getpid(); /* シグナルハンドラー登録 */ signal(SIGCONT, handler); /* 親プロセスに「スタンバイ ok!」を知らせる */ ptr->flag[PARENT] = OFF; kill(ptr->id_number[PARENT], SIGCONT); while (1) { /* 親プロセスからのシグナルを待つ */ pause(); if (ptr->flag[CHILD] != OFF) // 計算終了 break; else { // 計算開始 fprintf(stderr, " And sub program runninng now. "); fflush(stderr); pi_calc(&ptr->shmem2); fprintf(stderr, "\n"); ptr->flag[PARENT] = OFF; kill(ptr->id_number[PARENT], SIGCONT); } } if (shmdt(shmaddr) == -1) { perror("Shared menory closed"); exit(1); } return 0; } /* 円周率の計算 */ void pi_calc(double *sum) { int i; double step, temp; step = 1.0 / (double)TIMES; *sum = 0.0; /* データ並列、後半部分を受け持つ */ for (i = (TIMES / DIVIDED) + 1; i <= TIMES; i++) { temp = (i - 0.5) * step; *sum += 4.0 / (1.0 + temp * temp); } *sum *= step; } /* 何もしないシグナル処理関数 */ void handler(int dummy) { ; } ----- ここまで ----- /* 共通事項リストアップ・定義等ヘッダーファイル * file name: xxx3.h * * プロセス間での共通項を列挙し、不用意な間違いを少なくする。 * Cの線形構造を利用する。 */ #define PROCS 3 /* 全プロセス数 */ #define CHILD 1 /* 子プロセス1 */ #define PARENT 0 /* 親プロセス */ #define ON 1 #define OFF 0 #define TIMES 1000000000 /* 1億回 */ #define DIVIDED 2 /* dual core */ struct set1 { /* common variable */ double shmem1, shmem2; /* data buffer */ signed char flag[PROCS]; /* condition flag */ pid_t id_number[PROCS]; /* id code */ } *ptr;