How to map QtConcurrent on a QList of QVector<double> and reduce into one QVector

5.5k views Asked by At

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.

1

There are 1 answers

12
Marek R On BEST ANSWER

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.