ich habe ein Programm geschrieben, das über das Monte-Carlo-Prinzip Pi approximiert und dieses Programm mit OpenMP parallelisiert:
Es funktioniert, indem man auf das Quadrat mit den Eckpunkten (0,0), (0,1), (1,0) und (1,1) gleichverteilt Punkte "regnen" lässt und anschließend prüft, wie viele davon im Einheitskreis liegen. Über das Verhältnis kommt man dann an die Zahl Pi.
Code: Alles auswählen
#include <iostream>
#include <omp.h>
#include <cmath>
#include <ctime>
#include <climits>
using namespace std ;
// **********************************************************
double randomNumGen(double low, double high)
{
double range = high - low ;
double num = static_cast<double>( rand() ) * range / static_cast<double>( RAND_MAX ) + low ;
return num ;
}
// **********************************************************
int main()
{
// const unsigned long long int precision(ULLONG_MAX-1) ; // 18446744073709551614
const unsigned long long precision(200000000) ;
const double pi(3.1415926535897932) ;
srand(time( NULL ));
unsigned long long int inside(0) ;
cout << precision << endl ;
// ----------------------------------------------------------
#pragma omp parallel
{
double length( 1.0 / omp_get_num_threads() ) ;
int no( omp_get_thread_num() ) ;
double left( no * length ) ;
double right( (no+1) * length ) ;
double x(0.0), y(0.0) ;
#pragma omp for reduction( + : inside )
for( unsigned long long int k = 0 ; k < precision ; k++ )
{
x = randomNumGen(left, right) ;
y = randomNumGen(0.0, 1.0) ;
if( y*y <= 1.0 - x*x )
inside++ ;
}
}
// ----------------------------------------------------------
cout.setf(ios::fixed, ios::floatfield) ;
cout.precision(6) ;
cout << "Inside: " << inside << " (of " << precision << ")" << endl ;
cout << "Pi: " << pi << endl ;
long double tmp( (long double)inside / (long double)precision ) ;
cout << "Ratio: " << 4.0 * tmp << endl ;
return 0 ;
}
/* output :
Inside: 157076482 (of 200000000)
Pi: 3.141593
Pi(Ratio): 3.141730
*/
Code: Alles auswählen
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsRectItem>
#include <omp.h>
#include <cmath>
#include <ctime>
// **********************************************************
double randomNumGen(double low, double high)
{
double range = high - low ;
double num = static_cast<double>( rand() ) * range / static_cast<double>( RAND_MAX ) + low ;
return num ;
}
// **********************************************************
int main( int argc, char **argv )
{
const int breiteScene(600) ;
const int breiteItems(500);
QApplication app( argc, argv );
QGraphicsScene scene( QRect( -breiteScene/2, -breiteScene/2, breiteScene, breiteScene ) );
QGraphicsRectItem *rectItem = new QGraphicsRectItem(
QRect( -breiteItems/2, -breiteItems/2, breiteItems, breiteItems ), 0, &scene );
rectItem->setPen( QPen( Qt::red, 3 ) );
QGraphicsEllipseItem *ellipseItem = new QGraphicsEllipseItem(
QRect( -breiteItems/2, -breiteItems/2, breiteItems, breiteItems ), 0, &scene );
ellipseItem->setPen( QPen( Qt::red, 3 ) );
QGraphicsView view;
view.setScene( &scene );
view.show();
//------------------- OpenMP part -----------------------------
const unsigned long long int precision(100000) ;
// const double pi(3.1415926535897932) ;
srand(time( NULL ));
unsigned long long int inside(0) ;
#pragma omp parallel
{
double length( 1.0 / omp_get_num_threads() ) ;
int no( omp_get_thread_num() ) ;
double left( no * length ) ;
double right( (no+1) * length ) ;
double x(0.0), y(0.0) ;
#pragma omp for reduction( + : inside )
for( unsigned long long int k = 0 ; k < precision ; k++ )
{
x = randomNumGen(left, right) ;
y = randomNumGen(0.0, 1.0) ;
if( y*y <= 1.0 - x*x )
{
inside++ ;
#pragma omp critical
{
scene.addRect( QRectF( (x*breiteItems/2), (y*breiteItems/2), 1, 1), QPen( Qt::green ) );
scene.update( 0, 0 , breiteItems, breiteItems ) ;
}
}
else
#pragma omp critical
{
scene.addRect( QRectF( (x*breiteItems/2), (y*breiteItems/2), 1, 1), QPen( Qt::darkBlue ) );
scene.update( 0, 0 , breiteItems, breiteItems ) ;
}
}
}
return app.exec();
}
Anstatt das beregnete Quadrat sukzessive zu füllen, werden die Punkte zuerst alle berechnet und nachdem der parallele Abschnitt absolviert wurde, wird die Graphik gefüllt.
Wie kann ich das von mir gewünschte Verhalten erreichen ?
Ist das Design soweit OK oder sollte ich da was ändern ?
Abschließend sei noch angemerkt, dass ich relativ neu bei Qt und für jeden Support dankbar bin
Viele Grüße,
Trash
.