ノート
訪問者数 2593      最終更新 2013-01-05 (土) 10:41:29

2009/07/19 OpenMP メモ

OpenMPコンパイル

OpenGLとの共存

考え方は、OpenMPでのparallelで、GL表示側と計算側を並列起動する。

      +--------> GL表示側プログラム
      |                 ↑  読出し
      |             +--------+
 -----+             |共有変数| (計算進行状態を図形表示〜塗りつぶし)
      |             +--------+
      |                 ↑ 書き込み
      +--------> 計算側プログラム

更に、計算側プログラム内を並列化し、実際に並列計算を行う。

実行時に、環境変数 OMP_NUM_THREADS を適宜セットすること。さもないと、デフォルト値の1が使われて、並列実行しない。bashの場合

OMP_NUM_THREADS=8
export OMP_NUM_THREADS

OpenGLとの共存の例

#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);
        }
}
}

Nested Parallelの指定

oreganoでの並列状態の確認の一方法

区分求積法によるpiの計算例

/*                                        */
/* 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                /* グラフ表示の解像度 */

実行中の様子(VNCクライアント上でスクリーンキャプチャ) Pi_OMP.png

OpenMP参考資料


添付ファイル: filePi_OMP.png 901件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2013-01-05 (土) 10:41:29 (3735d)