Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: [Solved] SFML and OpenMP  (Read 3371 times)

0 Members and 1 Guest are viewing this topic.

tmac

  • Guest
[Solved] SFML and OpenMP
« on: July 07, 2008, 10:20:20 pm »
Hello, I'm working on a (Monte Carlo) physics simulation program. I have found that it is very simple to have parallell independent simulations on multi-core CPUs by using OpenMP. This is because each simulation is essentially independent of the others in my program.

But I want to be able to see a visualization of each simulation (one for each CPU-core), so I hoped that it would be as simple as letting OpenMP parallellize the SMFL code just as it does with the main simulation code. But when I start an OpenMP parallellized SFML program I get unpredictable behaviour, e.g. as with the program given below: Sometimes a window appears and disappears too fast to see if it is one or two windows, sometimes it hangs without any windows, and sometimes a window appears and hangs there.

Here is the program that gives the behaviour described above:

#include <SFML/Window.hpp>

int main() {
#pragma omp parallel num_threads(2)
  {
     sf::Window App(sf::VideoMode(640, 480, 32), "Title");
  }
   return(0);
}

I compile it with "g++ program.cpp -lsfml-window -fopenmp". Compiling without the -fopenmp or without the #pragma gives the correct behaviour: a window that appears and disappears before the programme quits.

I am hoping that I will be able to have two windows with OpenGL renderings of each simulation thread, and that the code will be short and simple. I have been through FreeGLUT, VTK and SDL before I heard of SFML. VKT was able to do it but I could never get a good keyboard interaction in the parallellized version.

Best regards,
Torquil Sørensen

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32502
    • View Profile
    • SFML's website
    • Email
[Solved] SFML and OpenMP
« Reply #1 on: July 08, 2008, 02:49:45 am »
What if you use regular threads instead of OpenMP ? Is the behaviour the same ?
Laurent Gomila - SFML developer

tmac

  • Guest
[Solved] SFML and OpenMP
« Reply #2 on: July 08, 2008, 12:01:20 pm »
Ok, I tried to create an analogous example using pthreads. It shows that the threads never continue beyond the sf::Window constructor, because the "Debug2" message is never printed.

Keep in mind that I just wanted a "trivial" way of visualizing my parallell simulations in separate windows. I assume that this can be done if it is done right, but it would maybe be somewhat more involved that this. But it would be practical if something like this did work :-)

#include <SFML/Graphics.hpp>
#include <iostream>

using namespace std;

void* testSfml(void* a)
{
   cout << "Debug1" << endl; // Prints OK
   
   sf::Window App(sf::VideoMode(100, 100, 32), "Title");

   cout << "Debug2" << endl; // Never prints

   return(0);
}

int main()
{
   pthread_t thread1, thread2;

   pthread_create(&thread1, 0, testSfml, 0);
   pthread_create(&thread2, 0, testSfml, 0);

   return(0);
}

tmac

  • Guest
[Solved] SFML and OpenMP
« Reply #3 on: July 08, 2008, 12:10:48 pm »
Btw, I forgot to mention that the pthreads program always just exited immediately when I ran it. I didn't hang or display any windows, as opposed to the OpenMP case. I ran it hundreds of times in a bash while-loop without ever seing a window or freeze.

Best regards
Torquil Sørensen

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32502
    • View Profile
    • SFML's website
    • Email
[Solved] SFML and OpenMP
« Reply #4 on: July 08, 2008, 12:23:44 pm »
This program exits immediatly, so whether it works or not you won't see anything ;)

Put a sf::Sleep(5) for example.
Laurent Gomila - SFML developer

tmac

  • Guest
[Solved] SFML and OpenMP
« Reply #5 on: July 08, 2008, 12:44:45 pm »
Sorry about that, I fact I forgot to use pthread_join() after pthread_create() in main(). Now it behaves isimilarly to the OpenMP case. I also put in a sf::Sleep() to be able to see how many windows are actually created.

The result is:
Sometimes it creates two windows and then exits, which it what I want. Other times it hangs between "Debug1" and "Debug2", without displaying any windows. At least these are the possibilities I have seen after having I run it 10-20 times now.

To avoid any confusion, here is the updated code:

#include <SFML/Window.hpp>
#include <iostream>

using namespace std;

void* testSfml(void* a)
{
   cout << "Debug1" << endl;
   
   sf::Window App(sf::VideoMode(100, 100, 32), "Title");

   sf::Sleep(1);

   cout << "Debug2" << endl;

   return(0);
}

int main()
{
   pthread_t thread1, thread2;

   pthread_create(&thread1, 0, testSfml, 0);
   pthread_create(&thread2, 0, testSfml, 0);

   pthread_join(thread1, 0); pthread_join(thread2, 0);

   return(0);
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32502
    • View Profile
    • SFML's website
    • Email
[Solved] SFML and OpenMP
« Reply #6 on: July 08, 2008, 12:46:38 pm »
What about the standard error output ? Any message ?
Laurent Gomila - SFML developer

tmac

  • Guest
[Solved] SFML and OpenMP
« Reply #7 on: July 08, 2008, 12:55:28 pm »
Nothing is printed to my terminal except for my own cout statements in the program. And I do not get any compiler warnings either. I compile with g++ -Wall.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32502
    • View Profile
    • SFML's website
    • Email
[Solved] SFML and OpenMP
« Reply #8 on: July 08, 2008, 03:02:11 pm »
Okay... looks hard to debug :D

Thanks for your feedback, I'll let you know if I can manage to solve it.
Laurent Gomila - SFML developer

tmac

  • Guest
[Solved] SFML and OpenMP
« Reply #9 on: July 09, 2008, 02:53:44 pm »
Hello again Laurent,

Thanks for your very valuable help. I have now been able to write an OpenMP-parallelized program that will be just what I need for my physical simulation.
Instead of declaring a sf::Window object in each thread, I instead use a pointer, and take care to not use the contructor of the object simultaneously. This is possible to do with OpenMP by means of the line #pragma omp critical.
Now I think it works beautifully. Compiling without -fopenmp will result in a program that is for just one processsor. I have chosen to specify the number of threads to use as a command line parameter. I run the program as e.g. "openmp.elf 3" to get three threads.

SFML is certainly good for visualizing simulations like the one I am working on, and it is very elegant. My simulation calculates a path-integral by means of the Monte Carlo method. In this context, path-integral means the integral of a function over a path-space, in this case a space of closed paths.
So I construct a lot of polygon paths, and add up certain contributions as the simulations runs. It is important to be able to see the polygons at least when debugging, because that is a very good way to discover problems with the algorithm.

Thanks again for your help,
Torquil Sørensen

Here is some OpenMP-parallelized SFML code:

Code: [Select]

#include <SFML/Window.hpp>
#include <iostream>

using namespace std;

#ifdef _OPENMP
extern "C" {
int omp_get_thread_num();
int omp_set_num_threads(int);
int omp_get_num_threads();
}
#endif

GLint* mkDispList() {
GLint* dispList = new GLint;

*dispList = glGenLists(1);

const double l = 1.0;
const double xmin = -l, xmax = l, ymin = -l, ymax = l, zmin = -l, zmax = l;

glNewList(*dispList, GL_COMPILE);

glColor3f(1.0, 1.0, 1.0);
glBegin(GL_LINE_LOOP);
glVertex3f(xmin, ymin, zmin); glVertex3f(xmax, ymin, zmin);
glVertex3f(xmax, ymax, zmin); glVertex3f(xmin, ymax, zmin);
glEnd();
glBegin(GL_LINE_LOOP);
glVertex3f(xmin, ymin, zmax); glVertex3f(xmax, ymin, zmax);
glVertex3f(xmax, ymax, zmax); glVertex3f(xmin, ymax, zmax);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(xmax, ymax, zmin); glVertex3f(xmax, ymax, zmax);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(xmin, ymax, zmin); glVertex3f(xmin, ymax, zmax);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(xmin, ymin, zmin); glVertex3f(xmin, ymin, zmax);
glEnd();
glBegin(GL_LINE_STRIP);
glVertex3f(xmax, ymin, zmin); glVertex3f(xmax, ymin, zmax);
glEnd();

glEndList();

return(dispList);
}

int main(int argc, char** argv)
{
const int wInit = 320, hInit = 240;

#ifdef _OPENMP
cout << "Using OpenMP with " << atoi(argv[1]) << " thread(s)" << endl;
omp_set_num_threads(atoi(argv[1]));
#else
cout << "Not using OpenMP. There will only be one thread" << endl;
#endif

#pragma omp parallel
{
sf::Window* Win;
int threadNum = 0;

#ifdef _OPENMP
threadNum = omp_get_thread_num();
#endif

float sphCamPos[3];
sphCamPos[0] = 5.0; sphCamPos[1] = 0.0; sphCamPos[2] = 0.0;

#pragma omp critical
{
Win = new sf::Window(sf::VideoMode(wInit, hInit, 32), "Window");
cout << "Thread " << threadNum << " has created its window" << endl;

glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, wInit, hInit);
gluPerspective(45, float(wInit)/hInit, 1, 1000);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
}

#pragma omp barrier

GLint* dispList = mkDispList();
usleep(100000);

#pragma omp barrier

for(int f = 0; f != 1000; ++f) {
cout << "Thread " << threadNum << " is simulating" << endl;
// Do simulation here
usleep(10000);
// Plot
#pragma omp critical
{
if(Win->IsOpened()) {
cout << "Thread " << threadNum << " is plotting its frame " << f << endl;
Win->SetActive(true);
sf::Event Event;
while(Win->GetEvent(Event)) {
if(Event.Type == sf::Event::Closed) {
Win->Close();
}
if((Event.Type == sf::Event::KeyPressed)
&&(Event.Key.Code == sf::Key::Escape)) {
Win->Close();
}
}

// Plot simulation state
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glCallList(*dispList);
Win->Display();
Win->SetActive(false);
}
}
}
}

return(0);
}

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32502
    • View Profile
    • SFML's website
    • Email
[Solved] SFML and OpenMP
« Reply #10 on: July 09, 2008, 03:07:07 pm »
I'm glad you finally managed to make SFML work with OpenMP :)
Laurent Gomila - SFML developer