PDA

View Full Version : QtConcurrent Questions and Clarifications



OzQTNoob
22nd November 2012, 02:39
Hi all experienced types,
I have a couple of questions about using QtConcurrent. So I spent days and days just trying to get something to actually run in another thread (not a simple QImage example - so sick of seeing those) but one where I needed a member function from one of my own classes. A have read and read various posts, articles, TFM etc and find it very esoteric to be be truthful. I am not bagging the various sources just my lack of C++ and Qt experience. So firstly,

1) if I instantiate and object in my code;

SomeClass *myClass = new SomeClass(arg1, arg2,..,this)
and then use QtConcurrent to start a trhead;

QFuture<T> = QtConcurrent::run(myClass,&SomeClass::myFunction, newarg1, newarg2) for example. Is QtConcurrent::run using the myClass object internal variables when it runs myFunction (and assuming myFunction requires these but not through the call to the function)? e.g. I have a private variable arg1 which was set in the constructor and which myFunction uses as well.

2) If I want to use QtConcurrent::mapped (which still fails me, and yes the documentation I am sure is fantastic but confusing to me) is the only way for me to get it to use a function that has multiple arguments to use boost::bind or the other suggested one? Otherwise it seems, and correct me if I am wrong, that I am only able to run a function that ever takes a singular input (which seems really, really limiting) EDIT: found this link on the wiki but not really what I was afterhttp://developer.qt.nokia.com/wiki/QtConcurrent-BlockingMapped-Other-Object-Member-Function-Operator

3) Can anyone tell me what the error message here is referring to. I suspect its something simple but I don't understand what it is that I have done wrong;

C:\Qt_projects\DrillDown\DrillDown\feature_finder. cpp:582: error: C2679: binary '=' : no operator found which takes a right-hand operand of type 'QFuture<void>' (or there is no acceptable conversion)
c:\qtsdk\desktop\qt\4.8.1\msvc2010\include\qtcore\ qvector.h(125): could be 'QVector<T> &QVector<T>::operator =(const QVector<T> &)'
with
[
T=QVector<QVector<QVector<double>>>
]
c:\qtsdk\desktop\qt\4.8.1\msvc2010\include\qtcore\ qvector.h(127): or 'QVector<T> QVector<T>::operator =(QVector<T> &&)'
with
[
T=QVector<QVector<QVector<double>>>
]
while trying to match the argument list '(QVector<T>, QFuture<void>)'
with
[
T=QVector<QVector<QVector<double>>>
]

The offending line of code is below and is called (or not in this case) in a member function of the feature_finder class. Extraction is also a member function of feature_finder, albeit one I have had to try and tweak down to a singular input argument.

QVector<QVector<QVector<QVector<double> > > > future;
future = QtConcurrent::mapped(spectrain,&feature_finder::Extraction);
I am more interested in knowing if anyone has seen the same error can let me know what it means (I understand that it is saying that the right hand side returns a future<void> but why?
I have tried what seems like a million variants on the above usage and f&*ked if I can get it to work in any capacity what so ever (go easy on me I am a NOOB)

Cheers
Oz

wysota
22nd November 2012, 03:34
1) if I instantiate and object in my code;

SomeClass *myClass = new SomeClass(arg1, arg2,..,this)
and then use QtConcurrent to start a trhead;

QFuture<T> = QtConcurrent::run(myClass,&SomeClass::myFunction, newarg1, newarg2) for example. Is QtConcurrent::run using the myClass object internal variables when it runs myFunction (and assuming myFunction requires these but not through the call to the function)? e.g. I have a private variable arg1 which was set in the constructor and which myFunction uses as well.
Yes, it does if myFunction() calls them.


2) If I want to use QtConcurrent::mapped (which still fails me, and yes the documentation I am sure is fantastic but confusing to me) is the only way for me to get it to use a function that has multiple arguments to use boost::bind or the other suggested one?
Yes and no. mapped() doesn't allow you to pass custom arguments to the call but you can do it by having a functor where you can set those arguments prior to calling mapped().


3) Can anyone tell me what the error message here is referring to. I suspect its something simple but I don't understand what it is that I have done wrong;
Your call to mapped() does not return vector of vectors of vectors of vectors of doubles. What does your Extraction() method accept as its argument and what does it return?

OzQTNoob
22nd November 2012, 04:04
Hi Wysota,

The Extraction function takes a
QVector<double> as its input and represents a single instance of the mapped input sequence (which I have just noticed is named the same thing e.g spectrain) The mapped spectrain is of the form
QVector<QVector<double> > . The actual declaration of Extraction within the feature_finder class is given below

QVector<QVector<QVector<QVector<double> > > > feature_finder::Extraction(QVector<double> spectrain)

Can you expand a little on the

mapped() doesn't allow you to pass custom arguments to the call but you can do it by having a functor where you can set those arguments prior to calling mapped(). bit. If I can have a functor set these prior to the call to mapped() then it would help me a lot.

I am processing a large volume of spectral data and to avoid my UI losing responsiveness (I read your excellent article on keeping the UI responsive) plus wanting to come to grips with the whole threading thing (speedups and the like) have gone down this path. Since I cant send any updates via QtConcurrent::run it didn't really seem the right way to go, and because it blocked (that is more likely my doing things incorrectly) it didnt appear to offer me any advantage.

Cheers
Oz

wysota
22nd November 2012, 04:37
Hi Wysota,

The Extraction function takes a
QVector<double> as its input and represents a single instance of the mapped input sequence (which I have just noticed is named the same thing e.g spectrain) The mapped spectrain is of the form
QVector<QVector<double> > . The actual declaration of Extraction within the feature_finder class is given below

QVector<QVector<QVector<QVector<double> > > > feature_finder::Extraction(QVector<double> spectrain)
This is a correct call to mapped then:


#include <QtConcurrentMap>
#include <QVector>

QVector<QVector<double> > mapFunc(const QVector<double> inData) {
return QVector<QVector<double> >();
}

int main(int argc, char **argv) {
QVector<QVector<double> > inVector;

QFuture<void> future = QtConcurrent::mapped(inVector, mapFunc);
return 0;
}

After the thread is done, "inVector" will contain the result of the call.


Can you expand a little on the
bit. If I can have a functor set these prior to the call to mapped() then it would help me a lot.
I'm not sure what to expand. The docs contain an example of using a functor (function object), just have a look at it.


Since I cant send any updates via QtConcurrent::run
Why not? You could post some custom events and then grab them and process them elsewhere.

OzQTNoob
22nd November 2012, 08:08
This is a correct call to mapped then:


#include <QtConcurrentMap>
#include <QVector>

QVector<QVector<double> > mapFunc(const QVector<double> inData) {
return QVector<QVector<double> >();
}

int main(int argc, char **argv) {
QVector<QVector<double> > inVector;

QFuture<void> future = QtConcurrent::mapped(inVector, mapFunc);
return 0;
}

After the thread is done, "inVector" will contain the result of the call.


I am a bit confused, sorry, as I thought that mapped allows you to return a Future of your own aka

QFuture<T> QtConcurrent::mapped ( const Sequence & sequence, MapFunction function )
I thought if I overwrite the original sequence then I am using the map form

QFuture<void> QtConcurrent::map ( Sequence & sequence, MapFunction function )

The return that comes from feature_finder::Extraction is of a totally different size, in terms of dimensions. The input Sequence consist of N spectral samples where each spectral sample contains X spectral bands [samples,spectral band]. The 4 dimensional output from feature_finder::Extraction after retrieving it from my Future is an array that would symbolically look like this [spectral variable, spectral region, spectral feature,sample]. Having actually just looked at this I think i actually have an error in my 4 dimensional return anyway don't I? Since the Future will build up the per-sample in its result when the mapped result returns e.g. my feature_finder::Extraction should only return a 3 dimensional array [spectral variable, spectral region, spectral feature]

Sorry about the further clarification. I am reading up on the functor (function object) as well

Cheers
oz

Added after 55 minutes:

Hi Wysota,

please ignore my previous post somewhat. I played with the code you posted and got it to work. I couldn't get it to overwrite the inVector though using the code you gave, but i was able to perform some operations on the inData and return a series based on the inVector Sequence (and to an arbitrary multidimensional array: and yeah i did stuff up the return in my Extraction function anyway was one dimension to large) . So many thanks. If I was to do the same thing within a class (my feature_finder class for example) then i presume that my mapping function would also not be a member function but rather a function of its own as in your example.

Cheers
Andrew

wysota
22nd November 2012, 08:11
I am a bit confused, sorry, as I thought that mapped allows you to return a Future of your own aka

QFuture<T> QtConcurrent::mapped ( const Sequence & sequence, MapFunction function )
I thought if I overwrite the original sequence then I am using the map form

QFuture<void> QtConcurrent::map ( Sequence & sequence, MapFunction function )
Indeed, my mistake, sorry. This works:


#include <QtConcurrentMap>
#include <QVector>

QVector<QVector<double> > mapFunc(const QVector<double> inData) {
return QVector<QVector<double> >();
}

int main(int argc, char **argv) {
QVector<QVector<double> > inVector;

QFuture<QVector<QVector<double> > > future = QtConcurrent::mapped(inVector, mapFunc);
return 0;
}