![]() |
ノート/OpenMPメモhttp://pepper.is.sci.toho-u.ac.jp/pepper/index.php?%A5%CE%A1%BC%A5%C8%2FOpenMP%A5%E1%A5%E2 |
![]() |
ノート
訪問者数 2593 最終更新 2013-01-05 (土) 10:41:29
考え方は、OpenMPでのparallelで、GL表示側と計算側を並列起動する。
+--------> GL表示側プログラム | ↑ 読出し | +--------+ -----+ |共有変数| (計算進行状態を図形表示〜塗りつぶし) | +--------+ | ↑ 書き込み +--------> 計算側プログラム
更に、計算側プログラム内を並列化し、実際に並列計算を行う。
実行時に、環境変数 OMP_NUM_THREADS を適宜セットすること。さもないと、デフォルト値の1が使われて、並列実行しない。bashの場合
OMP_NUM_THREADS=8 export OMP_NUM_THREADS
#include <stdio.h> #include <stdlib.h> #include <GL/glut.h> #include <math.h> #include <omp.h> #include "pi.h" double shape[DIV_NUM/RESOLUTION]; double h; void display(void) { int i; double x, y; glClear(GL_COLOR_BUFFER_BIT); glPointSize(5.0); glColor3f(1.0, 0.0, 0.0); /* red */ for (i=0; i<(DIV_NUM/RESOLUTION); i++) { //fprintf(stderr, "shape[%d]=%f\n", i, shape[i]); x = (double)i * h; y = shape[i]; //glBegin(GL_POINTS); //glVertex2d(x, y); //glEnd(); glRectd(x, 0.0, x+h, y); } /* End drawing points */ //glFlush(); /* Use glutSwapBuffers() instead of glFlush() for double buffering */ glutSwapBuffers(); } void init(void) { glEnable(GL_POINT_SMOOTH); glClearColor(1.0, 1.0, 1.0, 1.0); h = (RIGHT-LEFT)/ (double)(DIV_NUM/RESOLUTION); } void timer(int value) { glutPostRedisplay(); glutTimerFunc(10, timer, 0); } int GLmain(int argc, char *argv[]) { glutInit(&argc, argv); glutInitWindowSize(200,200); glutInitWindowPosition(0,0); //glutInitDisplayMode(GLUT_RGBA); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutCreateWindow(argv[0]); //glutFullScreen(); glutDisplayFunc(display); init(); glutTimerFunc(10, timer, 0); glutMainLoop(); return 0; } int PImain(int argc, char *argv[]) { int i; int j; double s; double u; #pragma omp parallel for private(j) reduction(+:s) for (i=0; i<(DIV_NUM); i++) { s = s + ((double)i/(double)DIV_NUM); if ( (i%RESOLUTION)==(RESOLUTION-1) ) { shape[i/RESOLUTION] = (double)i / (double)DIV_NUM; } } } int main(int argc, char *argv[]) { #pragma omp parallel sections { #pragma omp section { GLmain(argc, argv); } #pragma omp section { PImain(argc, argv); } } }
top - 20:19:11 up 5 days, 2:11, 4 users, load average: 0.76, 0.22, 0.20 Tasks: 193 total, 2 running, 191 sleeping, 0 stopped, 0 zombie Cpu0 : 63.6%us, 0.0%sy, 0.0%ni, 36.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu1 : 78.4%us, 1.0%sy, 0.0%ni, 20.6%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu2 : 65.8%us, 0.0%sy, 0.0%ni, 34.2%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu3 : 82.2%us, 0.0%sy, 0.0%ni, 17.8%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu4 : 86.0%us, 0.0%sy, 0.0%ni, 14.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu5 : 57.9%us, 0.0%sy, 0.0%ni, 42.1%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu6 : 61.0%us, 2.0%sy, 0.0%ni, 37.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Cpu7 : 53.8%us, 0.0%sy, 0.0%ni, 46.2%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 3373444k total, 986208k used, 2387236k free, 172812k buffers Swap: 5406712k total, 0k used, 5406712k free, 399508k cached
/* */ /* PI and GL integrated version of */ /* PI numerical integral calculation */ /* */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #include <sys/time.h> #include <GL/glut.h> #include <omp.h> #include "pi.h" double shape[DIV_NUM/RESOLUTION]; double h; /* 関数f(x) */ double f(double x) { return sqrt(1.0-x*x); } void display() { int i; double x, y; glClear(GL_COLOR_BUFFER_BIT); glPointSize(5.0); glColor3f(1.0, 0.0, 0.0); /* red */ for (i=0; i<DIV_NUM/RESOLUTION; i++) { // fprintf(stderr, "shape[%d]=%f\n", i, shape[i]); x = (double)i * h; y = shape[i]; glRectd(x, 0.0, x+h, y); } //glFlush(); /* Use gluSwapBuffers() instead of glFlush() for double buffering */ glutSwapBuffers(); } void init(void) { glEnable(GL_POINT_SMOOTH); glClearColor(1.0, 1.0, 1.0, 1.0); h = (RIGHT-LEFT) / (double)(DIV_NUM/RESOLUTION); } void timer(int value) { glutPostRedisplay(); glutTimerFunc(10, timer, 0); } int GLmain(int argc, char* argv[]) { glutInit(&argc, argv); glutInitWindowSize(200,200); glutInitWindowPosition(0,0); //glutInitDisplayMode(GLUT_RGBA); glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE); glutCreateWindow(argv[0]); //glutFullScreen(); glutDisplayFunc(display); init(); glutTimerFunc(10, timer, 0); glutMainLoop(); return 0; } int PImain(int argc, char *argv[]) { int i; int j; double s = 0; double temp; for (i=0; i<(DIV_NUM/RESOLUTION); i++) shape[i] = 0.0; #pragma omp parallel for private(temp) reduction(+:s) for (i=0; i<=DIV_NUM; i++) { temp = f(((double)i)/(double)DIV_NUM); s = s + temp; if ( (i%RESOLUTION) == (RESOLUTION-1) ) { shape[i/RESOLUTION] = temp; } } s = (s - (f(LEFT) + f(RIGHT))/2.0) / ((double)DIV_NUM); fprintf(stderr, "pi=%2.18f\n", s*4); } int main(int argc, char *argv[]) { struct timeval tv_start, tv_end; #pragma omp parallel sections { #pragma omp section { GLmain(argc, argv); } #pragma omp section { gettimeofday(&tv_start, NULL); /* 開始時刻測定 */ PImain(argc, argv); gettimeofday(&tv_end, NULL); /* 終了時刻測定 */ fprintf(stderr, "time=%8.6f\n", (double)(tv_end.tv_sec-tv_start.tv_sec)+(double)(tv_end.tv_usec-tv_start.tv_usec)/1000000.0); } } }
ただし、ヘッダーファイル pi.h は
#define LEFT 0.0 /* left edge of integration area */ #define RIGHT 1.0 /* right edge of integration area */ #define DIV_NUM 160000000 /* 全体の閾値の分割数 */ //#define DIV_NUM 16000 /* 全体の閾値の分割数 */ #define TH_NUM 8 /* スレッド数 */ #define RESOLUTION 10000 /* グラフ表示の解像度 */