Skip to content
  • 0 Votes
    24 Posts
    2k Views
    jsulmJ

    @Dean21 Please show your current code if something does not work...

  • 0 Votes
    8 Posts
    372 Views
    wcneillW

    @SGaist

    I got it to work by making the QFuture member variable of the class that was handling the GUI stuff, then just accessing it from the class I was working on above.

    if (engine) { // Engine has a QFuture<void> member for the models being loaded. We will watch it here. connect(&m_modelsLoadedWatcher, &QFutureWatcher<bool>::finished, this, &ConfigDialog::onNNModelsLoaded); // We know that the implementation of IEngine is Engine, so cast. m_modelsLoadedWatcher.setFuture(dynamic_cast<wise::Engine*>(engine)->m_modelsLoadedFuture); }

    Im curious however about the invokeMethod you were talking about. I started a new thread asking about it, as I did try it out: https://forum.qt.io/topic/140834/how-to-combine-qtconcurrent-with-qmetaobject-invokemethod.

  • 0 Votes
    1 Posts
    215 Views
    No one has replied
  • 0 Votes
    4 Posts
    275 Views
    V

    No, it's not about a performance issue.
    I was just not satisfied with leaving this function running until the end, since I already had my result and the rest will not bring me anything more.
    If I need to write it in a simple 'foreach' loop, I would write something like

    for( value : list ) if( value == search ) return true; return false;

    And I wanted to keep the same spirit with 'mappedReduced' (as long as this doesn't violate any "thread-rules" and without having to "hack" QtConcurrent).

    But yes, in fact I'm blocking my application untile I receive the results. My other methods that need to perform an action on all the items use 'blockingMapped', 'blockingMappedReduced' and 'blockingFiltered'. It's for a library that I am writing. And the applications that will use it are procedurale, not a GUI (or, maybe later...who knows?). But they may have to handle very long lists, and the 'compute' function are heavy. So QtConcurrent is a welcome help.

    I think I'll keep the first solution, the most elegant one in my eyes, if I don't get any warning.

  • 0 Votes
    2 Posts
    254 Views
    SGaistS

    Hi,

    If you want to use a member function, the array you pass to the map method must contain items of that class.

  • 0 Votes
    4 Posts
    276 Views
    Christian EhrlicherC

    Then please fill a bug report. Maybe there is already one.

  • 0 Votes
    16 Posts
    1k Views
    P

    @kshegunov
    That seems like a great resource! I will take a look.

  • 0 Votes
    17 Posts
    2k Views
    kshegunovK

    What is DataBuffer? And how do you render the data in the GUI thread?

  • 0 Votes
    6 Posts
    580 Views
    JKSHJ

    @CJha said in How to use full processing power available to do calculations?:

    If I use more threads by using QtConcurrent::mapped() or QThreadPool from inside a non-GUI thread, will it use this non-GUI calling thread as well? To make my point more clear: Let's say I create a thread called A and based on the number of cores my CPU has I have thread B, C and D available. After my thread A calls either QtConcurrent::mapped() or QThreadPool to start the calculation it has nothing more to do till the calculation finishes, so will it wait idle while my calculations are running in other threads or will QtConcurrent::mapped() or QThreadPool include thread A along with B, C and D to do the calculations?

    We need to know: How do you create thread A?

    QtConcurrent uses the global QThreadPool behind the scenes. If thread A is not part of the pool, then it won't be used by the pool to do calculations when it is idle.

    Is there any way I could run a single loop (major loop of my calculation) in multiple threads with different data sets without using QtConcurrent::run()? QtConcurrent::mapped() will not work as it has requirements that there should be a return type which is not always the case with my calculations. QThreadPool, QRunnable and especially QThreadPool::globalInstance() documentation is not enough for me to make this judgement.

    QtConcurrent::map() (not mapped()!) does not return any values. You can interface with it using QFuture<void>.

    See https://doc.qt.io/qt-5/qtconcurrentmap.html#concurrent-map

    Finally, is there a better/simpler approach to solving this problem?

    Experiment with QtConcurrent::map() and see if it suits your application.

    NOTE: I have placed the same question in Stack Overflow as well.

    As a courtesy to other users, please link your duplicate questions to each other. This way, people can see if your question has been resolved and get the answer too

  • 0 Votes
    7 Posts
    1k Views
    SGaistS

    Looks like you are re-implementing tools that already exist for that purpose. Was tmux/xpanes considered ?

    In any case, before doing any threading, you should have a proper encapsulation for your connection and command sending. Once you have that you can start thinking about threads or maybe use QtConcurrent. It looks like you rather have lists of commands to send to machines. A bit like what ansible manages for you with its playbook.

  • 0 Votes
    11 Posts
    2k Views
    R

    I CUDA not build it unfortunately. CUDA is only supported in Visual Studio for Windows so I guess its back to good old uncle GL ...

  • 0 Votes
    5 Posts
    634 Views
    D

    @sgaist said in Building a "complex" progress widget:

    Don't try to steal anything. Use signals and slots to communicate from your secondary threads back to your main thread.

    Yes, but as far as I can tell the main thread is "working" (or user has took control over it) as it spawned the secondary threads and is waiting for them to finish processing before moving on.

    Edit
    Ok so I've now run QMetaObject::invokeMethod(this,={callToLongFunction},Qt::QueuedConnection);
    This appear to work, however any loop that was being

    #pragma omp parallel for
    for (){}

    No longer threads... so qt somehow manages to break the omp multithreading ? -- well standalone teste indicates that no... all works there but my app stopped threading... sweet.

    Ok I'm a nub, its official! Everything works. It threads & runs job in qt internal event loop thus I don't have any issues. Wow. Ok I need to learn more on qt threading event loop :D I need to fork one for myself and have it process all my work stuff now :- ))

    EDIT...

    Ok seems like I did a full loop. I went from processing in user thread to processing in qt event loop - fine - but pragma still wont update the widget at the correct time... sigh. Since now we are in event loop, the processing of function is more important than processing of omp thread update signal... I need some kind of priority attached to signal to tell qt that hey... I know u have ur loop but process this signal now.
    Right now with Qt::DirectConnection while trying to update val/etc I get this >

    ###### WARNING: QWidget::repaint: Recursive repaint detected ((null):0, (null)) ###### ###### WARNING: QBackingStore::endPaint() called with active painter on backingstore paint device ((null):0, (null)) ######

    And aparently by putting this inside omp seems to "work"...

    if (omp_get_thread_num() == 0) { qApp->processEvents(); } ```... ahhhh multithreading <3
  • 0 Votes
    4 Posts
    1k Views
    S

    @VRonin
    Hi, thanks VRonin for the reply. Turns out the problem was to do with the library of FFTW that I used.

    I used separate threads to run functions from that library, which apparently are not thread safe. However, even with mutex locks they still wouldn't work. Back to the drawing board.

    Thanks.

  • 0 Votes
    6 Posts
    2k Views
    M

    @kshegunov said:

    You're missing the fact that QWidget and its descendants aren't reentrant.

    Actually, I missed more than that... I completely miss the fact that, when dealing with QWidget or simillar + threads, that exactely when I should have used signal/slot mechanism... I feel dumb about it, but anyway, the Crawler object now crawls using Qt::Concurrent and send a signal with the text to add to the QListWidget, and then a MainWidget's slot is called to create and add the item.

    Thanks for your help

  • 0 Votes
    2 Posts
    1k Views
    Chris KawaC

    Hi, welcome to the forum.

    Couple of things wrong here.

    First, to be able to pass a method like this it needs to be static, otherwise there's no instance to run it on.
    Second, to save you from unnecessary copies it should take the string as a const reference, not by value.
    Third, similar to above, to save yourself from copies where not needed you should use a const reference in the foreach variable declaration.
    Next, The return type of the function you pass should be the type of the element of the container, not the container itself i.e. QString in this case.
    And last but not least - the call to map() is not blocking, so it will return immediately and the function will exit. You passed a local string list to it so it means the asynchronous calls will operate on freed memory and most likely crash. If you want to wait for the results you should rather use blockingMap() instead and if not then you need to store that string list somewhere for the whole duration of the map() execution.

  • 0 Votes
    7 Posts
    5k Views
    jsulmJ

    As Chris Kawa already mentioned you should never try to access UI from another thread than the one where the UI is running!

  • 0 Votes
    12 Posts
    5k Views
    P

    @mjsurette

    That did the trick! I also removed the dataChanged() calls and now the operation executes instantly even with thousands of rows. It also seems there aren't any side effects, apart that I have to call again fetchMore() immediately after select(). I can now move on and implement some other batch operations like this without worrying about speed.

    Thank you!

  • 0 Votes
    1 Posts
    673 Views
    No one has replied