有人可以帮助我改进此代码并给我一些提示。我试图自己创建一个OpenMP版本的Mandelbrot。我是OpenMP初学者,在这里我没有加快速度,这可能是因为#pragma omp critical
,但我现在想不出更好的主意。
int main()
{
// picture resolution
int iX,iY;
const int ImageWidth = 1000;
const int ImageHeight = 1000;
double Cx,Cy;
const double CxMin=-2.5;
const double CxMax=1.5;
const double CyMin=-2.0;
const double CyMax=2.0;
double PixelWidth=(CxMax-CxMin)/ImageWidth; /* scaled x coordinate of pixel (must be scaled to lie somewhere in the Mandelbrot
X scale (-2.5, 1.5) */
double PixelHeight=(CyMax-CyMin)/ImageHeight;/* scaled y coordinate of pixel (must be scaled to lie somewhere in the Mandelbrot
Y scale (-2.0, 2.0) */
const int MaxColorComponentValue=255;
FILE * fp;
char *filename="MandelbrotSet.ppm";
char *comment="# ";// comment in ppm picture should start with #
unsigned char color[3]; // colors [R, G ,B]
// Z=Zx+Zy*i ; Z0 = 0
double Zx, Zy;
double Zx2, Zy2; // Zx2=Zx*Zx; Zy2=Zy*Zy
int Iteration;
const int IterationMax=150;
const double Bailout=2; // bail-out value
double Circle_Radius=Bailout*Bailout; // circle radius
fp= fopen(filename,"wb");
//write the header to the picture file
fprintf(fp,"P6\n %s\n %d\n %d\n %d\n",
comment,ImageWidth,ImageHeight,MaxColorComponentValue);
// For each pixel on the screen do:
// initialize_timer ( );
// start_timer ( );
omp_set_dynamic(1);
omp_set_num_threads(4);
#pragma omp parallel /*reduced(>:Circle_Radius)*/
{
#pragma omp for private(iY,iX,Iteration,Zx,Zy,Zx2,Zy2,color) \
schedule(dynamic) //or runtime
for(iY=0;iY<ImageHeight;iY++)
{
Cy=CyMin + iY*PixelHeight;
if (fabs(Cy)< PixelHeight/2) Cy=0.0; // Main antenna
#pragma omp critical
for(iX=0;iX<ImageWidth;iX++)
{
Cx=CxMin + iX*PixelWidth;
Zx=0.0;
Zy=0.0;
Zx2=Zx*Zx;
Zy2=Zy*Zy;
/* */
for (Iteration=0;Iteration<IterationMax && ((Zx2+Zy2)<Circle_Radius);Iteration++)
{
Zy=2*Zx*Zy + Cy;
Zx=Zx2-Zy2 +Cx;
Zx2=Zx*Zx;
Zy2=Zy*Zy;
};
if (Iteration==IterationMax)
{ // interior of Mandelbrot set = black
color[0]=0;
color[1]=0;
color[2]=0;
}
//
else{
color[0]=180;
color[1]=0;
color[2]=0;
// Gradient((double)(Iteration-log2(log2(sqrt(Zx2+Zy2))))/IterationMax,color);
}
fwrite(color,1,3,fp);
}
}
}
fclose(fp);
// stop_timer ( );
//
// printf("Elapsed time: %lf\n",elapsed_time ( ));
return 0;
}
答案 0 :(得分:5)
根据comment修复方法导致这些时间 1 :
没有openMP:
$ gcc -std=c99 -O3 -march=native mandel.c && time ./a.exe
real 0m12.324s
user 0m0.000s
sys 0m0.000s
启用openMP后:
User@IXL /cygdrive/e/mingw64
$ gcc -std=c99 -O3 -march=native -fopenmp mandel.c && time ./a.exe
real 0m3.619s
user 0m0.000s
sys 0m0.015s
输出印象:
...:.......... .... .............. ....;.=:./
.............:............ ........::::...... .... .......... .++^
.........^.:.....:;.........................:_::.:.........:::::. .....: ..:.^
........:::=;:=:.....::....................::=|;:........:....... .....::|:_.,=
..........:::==:;:.:::..............:::.)=;-`|`:-.......:::=,. ...... .....:==.:^ _
..........:<, ^./;;==:......::.......:_., -<;.........:`_;:............ . ..........-=:_,
...... ...:=' _,;;:.....:=v+`::::==, _,:::=|,.:;=+</+;... ::.:........................._.....'
......._,+;=^ "=:.:=<.:- _. ^ -^ ` "-`. =);)( "= ....:_,......................../=:.;-
...`:::::=-= =;. - _.(:.:..==-:......................+o(.
...........=<_ -^== :.==;...................= :_
.............:^:..., -:::.=<,............... .'-.
.... ............:.._.:.=,- .;:;:.............:v-_
..........:_,....:=`._/ --_.)(.:.........:/".
.......:,:;,;:=:::=` r`;,:........ =|`
........-=|=/.--.n` -"-+=........_/ ,
.. . ........^`:_, =::......._
.._.. ...........::-. ..,:....,.
...... ............._,::< -_,:..:./
..:...... ...................:.^` -'=::::=`
.... .........._..............:`_ i:::`
......:.........::.........:::v (::,
.....:_:...:..._;=:..::......:.>= ==;
.......:::::|=-:_,=-_.;=.:,:..::<, =`
...........::=o -` ^/):::_^ +
.... .....:......:_===^ _=;^ i
.................=:.:.::;` _=
..................-=+=;; -
..:;:...::....:::;%,
..:;:...::....:::;(`
.................:;;^=;;: _
.................::...::;, _/+
... ............:-=;=_, _.=`;. i
............::| _:_,.._.. .^":::- +
....... ;:;+``:-`;.=+;-^:`:.._.X` =,
......-:...:...-==:..::......:.>` -=;
......:.........::...........:"_ /::`
.... ..........-..............:,/ i:::,
..:...... ...................:^., _,=::::=`
...... .............-`::) _-`:..:+'
..... ...........:;_. !`:......-
.. .......:.,:=` -+".......-=
........_,<(=='=;<= _._>,;.......-\
...: . ...:=;. ..:=` >,|;:........ _=,
.:::......:......:{(+=< _==;=/............]v.
...........-.....`.:^_ -` ':;;.............:. /
.............:..-^`-` -=|;:^;=`...............:^}\.
...........=>- _.== :.==;...................= :!
...,:::::=_= =;. _ -.(:.:"^==_:......................+o(^
......-`|;=., _.=:.:-".:` - ._ _., | =+;-< .=:..:::-`........................\=:^<,
...... ..::;, ....-^;::.....;|:=,::::=-` -<=::=^`.::-;<=::... :...........................-.., |,
..........:"=,.+^:;++:......;:..... :={( ..=::."......:;=::......... .......:::-:/`
..........::;;::;:..::..............:.:-^`;__+::........::;-`. .... ....:;=+..__,=
........:_:; :;::........................:::;=;:........::...... .....;<,-.`-
.......:::.:.....:;....... ............:=:.^ .........;:.:.. .....: ..:"._,
.............:........... .......:::...... ... ........._..-
.......... . ... ..:........ .....:=:)(
........... ..:....... ..-.:s%=+'._,_/'_
........ ...:..... .. :.-<=::"_/_`-+.,
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <stdint.h>
#include <omp.h>
// picture resolution
static const int ImageWidth = 1000;
static const int ImageHeight = 1000;
static const double CxMin = -2.5;
static const double CxMax = 1.5;
static const double CyMin = -2.0;
static const double CyMax = 2.0;
int main()
{
double PixelWidth=(CxMax-CxMin)/ImageWidth; /* scaled x coordinate of pixel (must be scaled to lie somewhere in the Mandelbrot X scale (-2.5, 1.5) */
double PixelHeight=(CyMax-CyMin)/ImageHeight;/* scaled y coordinate of pixel (must be scaled to lie somewhere in the Mandelbrot Y scale (-2.0, 2.0) */
const int MaxColorComponentValue=1<<8;
typedef unsigned char pixel_t[3]; // colors [R, G ,B]
pixel_t *pixels = malloc(sizeof(pixel_t)*ImageHeight*ImageWidth);
//write the header to the picture file
FILE* fp;
#pragma omp parallel shared(pixels)
{
int iY;
#pragma omp for
for(iY=0; iY<ImageHeight; iY++) {
double Cy=CyMin + iY*PixelHeight;
if (fabs(Cy)< PixelHeight/2) {
Cy=0.0; // Main antenna
}
int iX;
for(iX=0; iX<ImageWidth; iX++) {
double Cx=CxMin + iX*PixelWidth;
double Zx=0.0;
double Zy=0.0;
double Zx2=Zx*Zx;
double Zy2=Zy*Zy;
/* */
int Iteration;
const int IterationMax=150;
const double Bailout=2; // bail-out value
const double Circle_Radius=Bailout*Bailout; // circle radius
for (Iteration=0; Iteration<IterationMax && ((Zx2+Zy2)<Circle_Radius); Iteration++) { //
Zy=2*Zx*Zy + Cy;
Zx=Zx2-Zy2 + Cx;
Zx2=Zx*Zx;
Zy2=Zy*Zy;
};
if (Iteration==IterationMax) {
// interior of Mandelbrot set = black
pixels[iY*ImageWidth + iX][0] = 0;
pixels[iY*ImageWidth + iX][1] = 0;
pixels[iY*ImageWidth + iX][2] = 0;
}
//
else {
pixels[iY*ImageWidth + iX][0] = ((double)(Iteration-log2(log2(sqrt(Zx2+Zy2))))/IterationMax) * MaxColorComponentValue;
pixels[iY*ImageWidth + iX][1] = 0;
pixels[iY*ImageWidth + iX][2] = 0;
}
}
}
}
//return 0; // TO BENCHMARK without free()/file IO
//write the header to the picture file
fp= fopen("MandelbrotSet.ppm","wb");
fprintf(fp,"P6\n %s\n %d\n %d\n %d\n","# no comment",ImageWidth,ImageHeight,MaxColorComponentValue);
for(int iY=0; iY<ImageHeight; iY++)
for(int iX=0; iX<ImageWidth; iX++)
fwrite(pixels[iY*ImageWidth + iX],1,sizeof(pixel_t),fp);
fclose(fp);
free(pixels);
// stop_timer ( );
//
// printf("Elapsed time: %lf\n",elapsed_time ( ));
return 0;
}
1 没有文件IO的时间(见代码中return
的评论)
答案 1 :(得分:0)
这是完整的代码。 谢谢你的帮助。
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <omp.h>
// #include "timer.h"
void Gradient();
// picture resolution
static const int ImageWidth = 1000;
static const int ImageHeight = 1000;
static const double CxMin = -2.5;
static const double CxMax = 1.5;
static const double CyMin = -2.0;
static const double CyMax = 2.0;
int main()
{
double PixelWidth=(CxMax-CxMin)/ImageWidth; /* scaled x coordinate of pixel (must be scaled to lie somewhere in the Mandelbrot X scale (-2.5, 1.5) */
double PixelHeight=(CyMax-CyMin)/ImageHeight;/* scaled y coordinate of pixel (must be scaled to lie somewhere in the Mandelbrot Y scale (-2.0, 2.0) */
const int MaxColorComponentValue=255;
typedef unsigned char pixel_t[3]; // colors [R, G ,B]
pixel_t *pixels = malloc(sizeof(pixel_t)*ImageHeight*ImageWidth);
FILE* fp;
// initialize_timer ( );
// start_timer ( );
#pragma omp parallel shared(pixels)
{
int iY;
#pragma omp for schedule(dynamic)
for(iY=0; iY<ImageHeight; iY++) {
double Cy=CyMin + iY*PixelHeight;
if (fabs(Cy)< PixelHeight/2) {
Cy=0.0; // Main antenna
}
int iX;
for(iX=0; iX<ImageWidth; iX++) {
double Cx=CxMin + iX*PixelWidth;
double Zx=0.0;
double Zy=0.0;
double Zx2=Zx*Zx;
double Zy2=Zy*Zy;
/* */
int Iteration;
const int IterationMax=50;
const double Bailout=2; // bail-out value
const double Circle_Radius=Bailout*Bailout; // circle radius
for (Iteration=0; Iteration<IterationMax && ((Zx2+Zy2)<Circle_Radius); Iteration++) { //
Zy=2*Zx*Zy + Cy;
Zx=Zx2-Zy2 + Cx;
Zx2=Zx*Zx;
Zy2=Zy*Zy;
};
if (Iteration==IterationMax) {
// interior of Mandelbrot set = black
pixels[iY*ImageWidth + iX][0] = 0;
pixels[iY*ImageWidth + iX][1] = 0;
pixels[iY*ImageWidth + iX][2] = 0;
}
//
else {
Gradient((double)((Iteration-log2(log2(sqrt(Zx2+Zy2)))))/IterationMax,pixels[iY*ImageWidth + iX]);
}
}
}
}
fp= fopen("MandelbrotSetNEW.ppm","wb");
fprintf(fp,"P6\n %s\n %d\n %d\n %d\n","# no comment",ImageWidth,ImageHeight,MaxColorComponentValue);
fwrite(pixels,sizeof(pixel_t),ImageWidth*ImageWidth,fp);
fclose(fp);
free(pixels);
// stop_timer ( );
//
// printf("Elapsed time: %lf \n",elapsed_time ( ));
return 0;
}
void Gradient(double position,unsigned char c[3])
{
if (position>1.0){
if (position-(int)position==0.0) position=1.0;
else position=position-(int)position;
}
unsigned char nmax=7; // number of color bars
double m=nmax*position;
int n=(int)m;
double f=m-n;
unsigned char t=(int)(f*255);
switch( n){
case 0: {
c[0] =0;
c[1] = t;
c[2] = 255;
break;
};
case 1: {
c[0] = 0;
c[1] = 255-t;
c[2] = 255;
break;
};
case 2: {
c[0] = t;
c[1] = 255;
c[2] = 0;
break;
};
case 3: {
c[0] = 255;
c[1] = 255 - t;
c[2] = 0;
break;
};
case 4: {
c[0] = t;
c[1] = 0;
c[2] = 255;
break;
};
case 5: {
c[0] = 255;
c[1] = 0;
c[2] = 255 - t;
break;
};
default: {
c[0] = 255;
c[1] = 0;
c[2] = 0;
break;
};
};
};