用OpenMP加速你的程序——以分形绘制为例

自从上次写了分形绘制后,一直在想办法加快程序运行,于是,自己就想到了多进程,但是,知道的办法不多,只是想到了fork还有OpenMP。

只是,我试了fork还有vfork后,效果不明显,不久没加快,反而降低了速度,而且,一旦创建多于1个进程,程序就出现莫名奇妙的错误。

与是,目前只能用OpenMP了,很简单,在你的for循环之上加上#pragma omp parallel for即可

然后用gcc或g++编译时加上“-fopenmp

效果很明显,速度加快不少,即使是1024x768的大小

以下是我修改过的分形绘制程序:

#include <cv.h>
#include <highgui.h>
#include <cxcore.h>
#include <stdio.h>

#define IMG_8UB(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x)] 
#define IMG_8UG(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x) + 1]
#define IMG_8UR(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[3 * (x) + 2]
#define IMG_32FB(img,x,y) ((float*)(img->imageData + img->widthStep * (y)))[3 * (x)] 
#define IMG_32FG(img,x,y) ((float*)(img->imageData + img->widthStep * (y)))[3 * (x) + 1]
#define IMG_32FR(img,x,y) ((float*)(img->imageData + img->widthStep * (y)))[3 * (x) + 2]
#define IMG8U(img,x,y) ((uchar*)(img->imageData + img->widthStep * (y)))[(x)] 

#define SMOOTH(x) ((sin((x)*2*3.1415926/510-3.1415926*0.5)+1)*0.5*255)

CvPoint pt1 = {-1, -1};
CvPoint pt2 = {-1, -1};
IplImage* fractal;
IplImage* fcopy;
int width = 1024;
int height = 768;
double XMax = 2.5;
double XMin = -2.5;
double YMax = 2.5;
double YMin = -2.5;

#define MAX_COLOR 1000
int B[MAX_COLOR];
int G[MAX_COLOR];
int R[MAX_COLOR];

struct Complex
{
    double real;
    double img;
};


char* name[100];
int fileIndex = 0;

char* itoa(int value)
{
    char* tmp = (char*) calloc(15, sizeof (char));
    char reverse[15];
    int index = 0;
    do
    {
        reverse[index++] = value % 10 + '0';
        value /= 10;
    }
    while (value);
    int size = index - 1;
    while (index--)
    {
        tmp[size - index] = reverse[index];
    }
    tmp[++size] = '.';
    tmp[++size] = 'j';
    tmp[++size] = 'p';
    tmp[++size] = 'g';
    tmp[++size] = '\0';
    return tmp;
}

void initFileName()
{
    for (int i = 1; i < 100; i++)
        name[i] = itoa(i);
}

void initColor()
{
    for (int i = 0; i < MAX_COLOR; i++)
    {
        //B[i] = (i + 70) % 256;
        B[i] = SMOOTH(i * 30 + 171);
        //G[i] = 0.7 * 255.0;
        G[i] = SMOOTH(i * 15 + 85);
        //R[i] = 255.0 * (1.0 - i / 255.0 * i / 255.0 / 1.2);
        R[i] = SMOOTH(i * 20);
    }
}

void drawPic()
{
    double deltaX = (XMax - XMin) / width;
    double deltaY = (YMax - YMin) / height;
    //int max_iterations = 256;
    double max_size = 4.0;
    #pragma omp parallel for
    for (int row = 0; row < height; row++)
    {
        #pragma omp parallel for//不知道这里行不行,但是,我编译没问题
        for (int col = 0; col < width; col++)
        {
            int color = 0;
            Complex c, z;
            z.real = 0;
            z.img = 0;
            c.real = XMin + col * deltaX;
            c.img = YMin + row * deltaY;
            //z.real = XMin + col * deltaX;
            //z.img = YMin + row * deltaY;
            //c.real = 0.285;
            //c.img = 0.01;

            while ((color < MAX_COLOR) && ((z.img * z.img + z.real * z.real) < max_size))
            {
                double tmp = z.real * z.real - z.img * z.img + c.real;
                z.img = z.img * z.real * 2 + c.img;
                z.real = tmp;
                color++;
            }
            if (color == MAX_COLOR)
            {
                IMG_8UB(fractal, col, row) = 0;
                IMG_8UG(fractal, col, row) = 0;
                IMG_8UR(fractal, col, row) = 0;
            }
            else
            {
                IMG_8UB(fractal, col, row) = B[color];
                IMG_8UG(fractal, col, row) = G[color];
                IMG_8UR(fractal, col, row) = R[color];

            }
            //color %= MAX_COLOR;
        }
    }
    //cvCvtColor(fractal,fractal,CV_HSV2BGR);
    //cvSaveImage(name[fileIndex++],fractal);
    //cvShowImage("Fractal",fractal);
    //cvCopy(fractal,fcopy); 
    //cvWaitKey(0);   
}

void on_mouse(int event, int x, int y, int flags, void *param = NULL)
{
    if (!fractal)
        return;

    if (event == CV_EVENT_LBUTTONDOWN)
    {
        pt1 = cvPoint(x, y);
    }
    else if (event == CV_EVENT_LBUTTONUP || !(flags & CV_EVENT_FLAG_LBUTTON))
    {
        pt2 = cvPoint(x, y);
        int dx = abs(pt2.x - pt1.x);
        int dy = abs(pt2.y - pt1.y);

        if (pt1.x > 0 && pt1.y > 0
                && pt2.x > 0 && pt2.y > 0
                && dx > 5 && dy > 5)
        {
            //cvSaveImage(name[fileIndex++], fcopy);
            double DX = XMax - XMin;
            double DY = YMax - YMin;
            double offX = DX / width;
            double offY = DY / height;
            if (pt1.x < pt2.x)
            {
                XMax = offX * pt2.x + XMin;
                XMin = offX * pt1.x + XMin;
            }
            else
            {
                XMax = offX * pt1.x + XMin;
                XMin = offX * pt2.x + XMin;
            }
            if (pt1.y < pt2.y)
            {
                YMax = offY * pt2.y + YMin;
                YMin = offY * pt1.y + YMin;
            }
            else
            {
                YMax = offY * pt1.y + YMin;
                YMin = offY * pt2.y + YMin;
            }
            pt1 = cvPoint(-1, -1);
            pt2 = cvPoint(-1, -1);
            printf("XMax:%.15lf XMin:%.15lf\nYMax:%.15lf YMin:%.15lf\n", XMax, XMin, YMax, YMin);
            double t = (double) cvGetTickCount() - t;
            drawPic();
            t = (double) cvGetTickCount() - t;
            printf("The time of is %.1f\n", t / (cvGetTickFrequency()*1000.));
            cvCopy(fractal, fcopy);
            //cvSaveImage(name[fileIndex++],fractal);
        }
    }
    else if (event == CV_EVENT_RBUTTONDOWN)
    {
        pt1 = cvPoint(-1, -1);
        pt2 = cvPoint(-1, -1);
    }
    else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))
    {
        pt2 = cvPoint(x, y);
        if (pt1.x > 0 && pt1.y > 0
                && pt2.x > 0 && pt2.y > 0
                && abs(pt2.x - pt1.x) > 5
                && abs(pt2.y - pt1.y) > 5)
        {
            cvCopy(fractal, fcopy);
            cvRectangle(fcopy, pt1, pt2, cvScalar(255, 255, 255));
            cvShowImage("Fractal", fcopy);
        }
    }
}

int main()
{
    cvNamedWindow("Fractal", 1);
    cvSetMouseCallback("Fractal", on_mouse, 0);
    fractal = cvCreateImage(cvSize(width, height), 8, 3);
    fcopy = cvCreateImage(cvSize(width, height), 8, 3);
    initFileName();
    initColor();

    drawPic();
    printf("Drow pic done!\n");
    cvShowImage("Fractal", fractal);
    //cvWaitKey(10);
    cvCopy(fractal, fcopy);
    //cvSaveImage(name[fileIndex++],fractal);

    while (cvWaitKey(1000) < 0)
    {
        cvShowImage("Fractal", fcopy);
    }

    cvReleaseImage(&fractal);
    cvReleaseImage(&fcopy);
    cvDestroyWindow("Fractal");
    for (int i = 0; i < 100; i++)
        free(name[i]);
    return 0;
}


你可能感兴趣的:(用OpenMP加速你的程序——以分形绘制为例)