Parallel programming Qt C++

Asked

Viewed 215 times

1

I’m starting to learn parallel programming, and I’m looking to compare a program with a single thread with a multi thread.

What I thought was to make a very simple algorithm that, in a 1-minute interval, would calculate as many prime numbers as possible, and, show me the last calculated prime number and its position in prime numbers, for example, let’s say it was number 23, would appear number 23 and its position, in case 9, because it is the 9th prime number.

I used Qtconcurrent to split the threads.

Without using parallelism, the number found was 117779, at position 119963. However, using parallelism, I obtained the number 198227, at position 17934 (wrong position and wrong number, this value is not prime and the previous cousin had position 17839, much lower than the position shown at the end). I believe I have to use the library , but I can’t find a way to implement in my code.

Below follows the code:

#include <QCoreApplication>
#include <qtconcurrentrun.h>
#include <QFutureSynchronizer>
#include <QThread>
#include <time.h>
#include <iostream>
using namespace std;

time_t endwait;

int ehPrimo(int num) {
    int  i;
    for (i=2; i<=num/2; i++)
        if (num%i==0) return 0;
    return 1;
}

void funcThread(QString name, int *p, int *n, int *u){
    while (time (NULL) < endwait){
        if(ehPrimo(*p)) {
            *n = *n + 1;
            *u = *p;
        }
        *p = *p + 2;
        //qDebug() << endl << name << " p"<<*p<<" n"<<*n<<" u"<<*u << "from: " << QThread::currentThread();
    }
}

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    int p = 5, n = 2, u=p;
    int seconds = 5;

    endwait = time (NULL) + seconds;

    QFuture<void> t1 = QtConcurrent::run(funcThread, QString("A"), &p,&n,&u);
    QFuture<void> t2 = QtConcurrent::run(funcThread, QString("B"), &p,&n,&u);
    QFuture<void> t3 = QtConcurrent::run(funcThread, QString("C"), &p,&n,&u);
    QFuture<void> t4 = QtConcurrent::run(funcThread, QString("D"), &p,&n,&u);


    t1.waitForFinished();
    t2.waitForFinished();
    t3.waitForFinished();
    t4.waitForFinished();

    cout << "\n\n Encontrou " << n << " primos.";
    cout << "\n\n Ultimo primo: " << u << ".\n\n";



    return a.exec();
}

1 answer

1

From what I understand, your code tries to do the calculation within a certain time frame, so I think it’s normal for the position to vary. About the wrong result (the number not being prime), I believe this happens because your threads are using their variables in the wrong order because their function is out of sync. This is called race condition.

When you "fire" a new thread, you have no control over it. You need to use some resource to prevent it from doing unexpected things like modifying a variable to the same as another thread or in a different order than you expect.

I used Qmutex to lock its function and the result here has always been a prime number.

time_t endwait;
QMutex mutex;

int ehPrimo(int num) {
    for (int i=2; i<=num/2; i++)
        if (num%i==0) return 0;
    return 1;
}

void funcThread(QString name, int *p, int *n, int *u) {
    QMutexLocker lock(&mutex);
    while (time (NULL) < endwait){
        if(ehPrimo(*p)) {
            *n = *n + 1;
            *u = *p;
        }
        *p = *p + 2;
    }
}

Search for thread synchronization and class Qmutex, Qwaitcondition, etc. http://doc.qt.io/qt-5/threads-synchronizing.html

Browser other questions tagged

You are not signed in. Login or sign up in order to post.