2

I really tried to combine everything I know in order to make this work. I believe there will be no problem with deadlock or other thread issues in the current structure. However, some pieces are missing, and the available documentation is not helping me (I am not experienced in C++ documentation).

int main() 
{
    QVector<double> vector_of_doubles(5);
    qFill(vector_of_doubles.begin(), vector_of_doubles.end(), 1);

    QList< QVector<double> > list_of_vectors;
    list_of_vectors.append(vector_of_doubles);
    list_of_vectors.append(vector_of_doubles);
    list_of_vectors.append(vector_of_doubles);

    QFuture< QVector<double> > res; 
    res = QtConcurrent::mappedReduced(list_of_vectors, Map(), Reduce());
    res.waitForFinished();
    qDebug()<<res.result();
    return 0
}

QVector<double> Reduce(QVector<double> vector)
// Here the vectors get combined into one big vector....but how?
{
    ....
    return big_vector;
}

QVector<double> Map(QVector<double> vector)
{
    for (int i = 0; i < vector.size(); i++)
    {
        vector[i] = vector[i] + i;
    }
    return vector;
}

From the input of QList holding 3 vectors with all ones, I would like to go into one vector, for which every vector has added some iteration variable. I would expect as a result in qDebug() to see:

{1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, 2, 3, 4 ,5}

Here what I assume to be the missing pieces:

  • What about the QtConcurrent:mappedReduced(), am I giving the correct arguments?
  • What about the functions returns, how should these be sorted out?
  • What exactly is needed to be included, do I just need to include QtConcurrent?
  • Once this starts working, and the list would be huge, as far as I understand QtConcurrent will do the thread management (use available cores), and all the items of the list (even if not the same size) will be passed smartly to the threads not to have them idle?

Edit (maybe it is a problem that it happens on a button click?):

While it was working for my example, what can be wrong when I use this:

Chokes on: res = QtConcurrent::mappedReduced(holder, correlate, Reduce, QtConcurrent::SequentialReduce);

Var: QList< QVector<double> > holder;

Functions involved:

QVector<double> correlate(QVector<double> &var1); 

and

void Reduce(QVector<double> &reduceResult, const QVector<double> &partial)`

error: no matching function for call to 'mappedReduced(QList<QVector<double> >&, <unresolved overloaded function type>, <unresolved overloaded function type>, QtConcurrent::ReduceOption)'

And also: "could not deduce template parameter ResultType"

It is the same thing as a working thing in the console application.

PascalVKooten
  • 20,643
  • 17
  • 103
  • 160

1 Answers1

2

Yep documentation of QtConcurrent is bad. Here is better description how mappedReduced should be used.

So reduce function should look like:

void joinVectors(QVector<double> &reduceResult, const QVector<double> &partial) {
    reduceResult += partial;
}

To keep proper order of data you should add extra argument:

res = QtConcurrent::mappedReduced(list_of_vectors, doSomeMapping, joinVectors, QtConcurrent::SequentialReduce);


Here is code I used for testing and it works (builds successfully and gives expected result):
#include <QCoreApplication>
#include <QtConcurrent/QtConcurrent>
#include <QDebug>

QVector<double> addIndexToVector(QVector<double> vector) {
    for (int i = 0; i < vector.size(); i++) {
        vector[i] = vector[i] + i;
    }
    return vector;
}

void joinVectors(QVector<double> &reduceResult, const QVector<double> &partial) {
    reduceResult += partial;
}

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);
    QVector<double> vector_of_doubles(20, 0);

    QList< QVector<double> > list_of_vectors;
    list_of_vectors.append(vector_of_doubles);
    list_of_vectors.append(vector_of_doubles);
    list_of_vectors.append(vector_of_doubles);

    QFuture< QVector<double> > res;
    res = QtConcurrent::mappedReduced(list_of_vectors, addIndexToVector, joinVectors);
    res.waitForFinished();
    qDebug()<<res.result();

    return a.exec();
}

Project file:

QT       += core concurrent
QT       -= gui
TARGET = testApp
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app

SOURCES += main.cpp

I used Qt 5.0.1 Linux version.

Marek R
  • 32,568
  • 6
  • 55
  • 140
  • Where doSomeMapping is my mapping function, joinVectors is the reduce function, and what is the last argument? – PascalVKooten Sep 01 '13 at 15:06
  • Ah found it in the documentation. I believe I can even use the unordered reduce. Is this argument neccessary? It seems to be omitted often. – PascalVKooten Sep 01 '13 at 15:12
  • Also, everything seems to be set up correctly, but I get `/usr/include/qt5/QtConcurrent/qtconcurrentmapkernel.h:96: error: undefined reference to `QtConcurrent::ThreadEngineBase::~ThreadEngineBase()'` – PascalVKooten Sep 01 '13 at 15:16
  • This has to be added to the project: `QT += (what is there already) concurrent` – PascalVKooten Sep 01 '13 at 15:18
  • 1. I change name to `doSomeMapping`since `Map` name is asking for trouble or ass kicking. 2. I recommend you `QtConcurrent::SequentialReduce` since it is more safe for you (I assuming that order of reduction is important). 3. I didn't had such error, `QtConcurrent` is in Qt Core module. 4. I will try to reproduce your problem after work. – Marek R Sep 02 '13 at 08:08
  • Thanks a lot in advance. It seems that the problem is somehow when using it in a GUI application. I use it in the MainWindow class, pretty much the same as in the Console. The errors pop up like mentioned, and I have no clue how to solve it. – PascalVKooten Sep 02 '13 at 09:15
  • Marek, could it be possible that there is an issue if the Mapper function contains a pointer? What is the solution? `QVector Mapper(QVector &var));` – PascalVKooten Sep 04 '13 at 21:05
  • sorry I didn't have time to work it out. I've checked this error and it is some template problem for sure, I need some time to figure out why it is unable to detect all template parameters. – Marek R Sep 05 '13 at 14:03
  • Ok I was wrong it was not template problem. Adding "QT += concurrent" in project file fixes the issue. – Marek R Sep 07 '13 at 20:46
  • Marek, unfortunately that is present in my `.pro` file :( – PascalVKooten Sep 08 '13 at 08:27
  • This is strange, I've had exactly same error message when this entry was missing. I will paste whole test code I used to test your error. – Marek R Sep 09 '13 at 07:59
  • I'm not sure if you revived notification about my answer edit, so: ping :). – Marek R Sep 10 '13 at 16:40