PDA

View Full Version : Converting OpenMP sections to QThreads



schludy
17th January 2012, 14:03
I am using a code that's written by somebody else, where he used OpenMP for Multi-Threading.

So I found out, that you can't use OpenMP threads and QThreads at the same time. That means I have to possible ways to make my GUI work:

1. Write my own BackgroundWorker, so that my GUI still works, when executing this function after a button click.
2. Rewrite my function, so that it is done in QThreads.

My problem with rewriting to QThreads is, that the code was not written very well:

It only has one class, with a lot of variables and functions, where the variables are changed inside the functions and across different sections.
The threading does something like this.


#pragma omp parallel sections
{
#pragma omp section
{ ....
}
#pragma omp section
{ ....
}
}


So my question is:
What is easier, writing a BackgroundWorker or rewriting the function?
Second, could you roughly outline a solution?

Thanks very much
schludy

wysota
17th January 2012, 14:30
Could you explain why your GUI won't work with OpenMP? What do you want to use threads for in your GUI?

schludy
17th January 2012, 14:54
The function that I'm calling runs in a loop for about 100 seconds and controls a robot. I want to be able to stop the process with the GUI and maybe output and modify some parameters.
I tried run the function as a QThread, but when the program gets to the #pragma command, I get a SIGSEGV Error. So I guessed that you can't create new OpenMP threads in a QThread.

wysota
17th January 2012, 15:09
Maybe you don't need the loop? How does your loop look like?

schludy
17th January 2012, 15:21
I have 3 parallel sections:
Image information from the robot are extractet and processed.
The robot computes new signals.
Communication with the robot.

This is from implementation in VS, with a background worker.


#pragma omp section
{
while ( (iFrame<=EndFrame) && (time<timeMax) )&& !worker->CancellationPending) {
...
}
}


The robot needs about 100 seconds to complete the task, so I think I can't get rid of the loop.
The program is quite big and confidential, so I can't really post a lot.

wysota
17th January 2012, 16:12
This while loop can safely be removed in favour of the Step-by-Step solution mentioned in this article: Keeping the GUI Responsive.

ars
17th January 2012, 16:49
If you are running on windows and using mingw 4.4 (mingw coming with Qt distribution) this link
http://gcc.gnu.org/bugzill/show_bug.cgi?id=42616 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=42616)
shows an error report on mingw 4.4 crashing when using openmp from a pthread. Maybe that's your crash too.

schludy
18th January 2012, 11:27
Ok, so it might just be a bug? I thought this is just not possible.

I use 32-bit Windows 7, and for MinGW I just used the one from QtSDK, that I downloaded with QtCreator.
I installed the newest version of MinGW and changed the System path to the new folder. Is that everything that I have to do, to use the newer MinGW. In Qt it still says MinGW4.4 ...

Anyways, it still crashes, at the line with the first #pragma omp.

I created a testcase, that is close to my program:



#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

private slots:
void on_pushButton_clicked();

private:
Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H


#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
#include <QThread>


MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}

MainWindow::~MainWindow()
{
delete ui;
}

void MainWindow::on_pushButton_clicked()
{
worker* wThread = new worker(this);
wThread->start();
}


#ifndef WORKER_H
#define WORKER_H

#include <QtCore>
#include <QThread>

class worker : public QThread
{
Q_OBJECT

public:
explicit worker(QObject *parent = 0);

protected:
void run();

};

#endif // WORKER_H


#include "worker.h"
#include "threads.h"
#include <QtCore>
#include <QThread>

worker::worker(QObject *parent) :
QThread(parent)
{
}

void worker::run()
{
threads thr;
thr.startThreads();
}


#ifndef THREADS_H
#define THREADS_H

class threads
{
public:
void startThreads();
};

#endif // THREADS_H


#include "threads.h"
#include <QDebug>
#include <omp.h>
#include <iostream>

using namespace std;

void threads::startThreads()
{

bool finished = false;

#pragma omp parallel sections
{
#pragma omp section
{
int a=0;
char outBuffer[500];
while(a<1000){
sprintf(outBuffer,"a: %d \n", a);
qDebug( outBuffer);
a++;
}
finished = true;

}
#pragma omp section
{
int b=0;
char outBuffer[500];
while( !finished ){
sprintf(outBuffer,"b: %d \n", b);
qDebug( outBuffer);
b++;
}
}
}

}

ars
18th January 2012, 20:30
I tried your example on my machine (dual core, Windows 7 64 bit, TDM mingw 32/64, version 4.5.2, Qt version 4.7.3) and it worked without problems in a 64 bit build. Unfortunately, it crashed when running the 32 bit build.

32 bit build also crashed when simplifying the StartThreads method to

#pragma omp parallel
{
cout << "id = " << omp_get_thread_num() << endl;
}
Again, 64 bit build worked fine.

wysota
18th January 2012, 23:07
Why don't you just get rid of this extra pthread?