自从上次写了分形绘制后,一直在想办法加快程序运行,于是,自己就想到了多进程,但是,知道的办法不多,只是想到了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; }