[英]OpenMP Fractal Generator
我一直在嘗試創建julia set的openMP變體,但在運行多個線程時無法創建一致的映像,我一直在嘗試解決看起來像競爭條件的問題,但是找不到錯誤。 令人討厭的輸出看起來像所需的輸出以及整個圖片上的“掃描線”。
如果代碼不夠清晰,我也會附加代碼。
#include <iostream>
#include <math.h>
#include <fstream>
#include <sstream>
#include <omp.h>
#include <QtWidgets>
#include <QElapsedTimer>
using namespace std;
double newReal(int x, int imageWidth){
return 1.5*(x - imageWidth / 2)/(0.5 * imageWidth);
}
double newImaginary(int y, int imageHeight){
return (y - imageHeight / 2) / (0.5 * imageHeight);
}
int julia(double& newReal, double& newImaginary, double& oldReal, double& oldImaginary, double cRe, double cIm,int maxIterations){
int i;
for(i = 0; i < maxIterations; i++){
oldReal = newReal;
oldImaginary = newImaginary;
newReal = oldReal * oldReal - oldImaginary * oldImaginary + cRe;
newImaginary = 2 * oldReal * oldImaginary + cIm;
if((newReal * newReal + newImaginary * newImaginary) > 4) break;
}
return i;
}
int main(int argc, char *argv[])
{
int fnum=atoi(argv[1]);
int numThr=atoi(argv[2]);
// int imageHeight=atoi(argv[3]);
// int imageWidth=atoi(arg[4]);
// int maxIterations=atoi(argv[5]);
// double cRe=atof(argv[3]);
// double cIm=atof(argv[4]);
//double cRe, cIm;
int imageWidth=10000, imageHeight=10000, maxIterations=3000;
double newRe, newIm, oldRe, oldIm,cRe,cIm;
cRe = -0.7;
cIm = 0.27015;
string fname;
QElapsedTimer time;
QImage img(imageHeight, imageWidth, QImage::Format_RGB888);//Qimagetesting
img.fill(QColor(Qt::black).rgb());//Qimagetesting
time.start();
int i,x,y;
int r, gr, b;
#pragma omp parallel for shared(imageHeight,imageWidth,newRe,newIm) private(x,y,i) num_threads(3)
for(y = 0; y < imageHeight; y++)
{
for(x = 0; x < imageWidth; x++)
{
newRe = newReal(x,imageWidth);
newIm = newImaginary(y,imageHeight);
i= julia(newRe, newIm, oldRe, oldIm, cRe, cIm, maxIterations);
r = (3*i % 256);
gr = (2*(int)sqrt(i) % 256);
b = (i % 256);
img.setPixel(x, y, qRgb(r, gr, b));
}
}
//stringstream s;
//s << fnum;
//fname= "julia" + s.str();
//fname+=".png";
//img.save(fname.c_str(),"PNG", 100);
img.save("julia.png","PNG", 100);
cout<< "Finished"<<endl;
cout<<time.elapsed()/1000.00<<" seconds"<<endl;
}
正如評論中指出的那樣,您有兩個主要問題:
newRe
和newIm
是共享的,但不應共享 r
, gr
和b
的訪問權限(我認為默認為共享) QImage::setPixel
要糾正此問題,請毫不猶豫地將omp for
循環嵌套在omp parallel
塊中。
在for
循環之前聲明私有變量:
為了防止同時調用QImage::setPixel
, 由於此函數不是線程安全的 ,因此可以將其放在#pragma omp critical
的關鍵區域中。
int main(int argc, char *argv[])
{
int imageWidth=1000, imageHeight=1000, maxIterations=3000;
double cRe = -0.7;
double cIm = 0.27015;
QElapsedTimer time;
QImage img(imageHeight, imageWidth, QImage::Format_RGB888);//Qimagetesting
img.fill(Qt::black);
time.start();
#pragma omp parallel
{
/* all folowing values will be private */
int i,x,y;
int r, gr, b;
double newRe, newIm, oldRe, oldIm;
#pragma omp for
for(y = 0; y < imageHeight; y++)
{
for(x = 0; x < imageWidth; x++)
{
newRe = newReal(x,imageWidth);
newIm = newImaginary(y,imageHeight);
i= julia(newRe, newIm, oldRe, oldIm, cRe, cIm, maxIterations);
r = (3*i % 256);
gr = (2*(int)sqrtf(i) % 256);
b = (i % 256);
#pragma omp critical
img.setPixel(x, y, qRgb(r, gr, b));
}
}
}
img.save("julia.png","PNG", 100);
cout<<time.elapsed()/1000.00<<" seconds"<<endl;
return 0;
}
更進一步,您可以節省一些CPU時間,將::setPixel
替換為::scanLine
:
#pragma omp for
for(y = 0; y < imageHeight; y++)
{
uchar *line = img.scanLine(y);
for(x = 0; x < imageWidth; x++)
{
newRe = newReal(x,imageWidth);
newIm = newImaginary(y,imageHeight);
i= julia(newRe, newIm, oldRe, oldIm, cRe, cIm, maxIterations);
r = (3*i % 256);
gr = (2*(int)sqrtf(i) % 256);
b = (i % 256);
*line++ = r;
*line++ = gr;
*line++ = b;
}
}
編輯:
由於茱莉亞集合似乎具有圍繞(0,0)
點的中央對稱,因此您只能執行微積分的一半:
int half_heigt = imageHeight / 2;
#pragma omp for
// compute only for first half of image
for(y = 0; y < half_heigt; y++)
{
for(x = 0; x < imageWidth; x++)
{
newRe = newReal(x,imageWidth);
newIm = newImaginary(y,imageHeight);
i= julia(newRe, newIm, oldRe, oldIm, cRe, cIm, maxIterations);
r = (3*i % 256);
gr = (2*(int)sqrtf(i) % 256);
b = (i % 256);
#pragma omp critical
{
// set the point
img.setPixel(x, y, qRgb(r, gr, b));
// set the symetric point
img.setPixel(imageWidth-1-x, imageHeight-1-y, qRgb(r, gr, b));
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.