Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to use full processing power available to do calculations?



  • Hi, I am working on a plotting application. In a single application, there are multiple plot areas and each of these plot areas has multiple line plots. Currently, I am creating a single QThread for each of the plot areas by subclassing QObject and using moveTothread() function to move these plot areas in their own thread where I perform the calculations to generate the line plots associated with each plot area. However, sometimes in my application, there is just one plot area that has many line plots, this makes using a single thread associated with that plot area to do all calculations sequentially highly inefficient as any extra threads available to my application is just sitting idle. I looked at Multithreading Technologies documentation and I am unable to figure out which approach to use to further distribute the calculation of each line plot from each plot area to as many threads as possible. My requirements are:

    • Distribute processing as much as possible
    • Be able to cancel long-running calculation in between
    • Do the calculation without blocking the GUI (the main reason why each plot area is in its own thread)

    Because of the first and second requirements above, I cannot use QtConcurrent::run() as it uses a single thread and cannot be paused/resumed/canceled. So, I am left with two choices:

    • QtConcurrent::mapped()
    • QThreadPool Specifically QThreadPool::globalInstance() as i do not want to manage the thredpool myself (want to give Qt and OS it's own space to manage threads without me being involved)

    Regarding the above two choices, I have a few questions which I was unable to find answer to anywhere else:

    • 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?
    • 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.
    • Finally, is there a better/simpler approach to solving this problem? The outline of my main loop to calculate final line plots is as follows:
    for(int ii = 0; ii < vectorData.length(); ++ii) // vectorData is QVector<QVector<double>>, there is a single vectorData for each plot area
    {
        for(int jj = 0; jj < vectorData[ii].length(); ++jj)
        {
            // Do the calculation to find raw values related to each x-pixel and store it in a vector
        }
        for(...) // This for loop depends on raw values calculated above
        {
            // Place the raw values calculated above to correct the y-pixel value
            // two inner for loops are needed as placing any raw values to correct y-pixel value requires knowledge of the next raw value
        }
    }
    

    If I could run just the above loop in a distributed manner in as many processor cores as available without blocking the GUI and with an ability to abort the calculation in between that would be ideal.

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



  • I would imagine, because you did not provide a starting point for code (like what you have tried), that your question will get ripped to shreds on SO. While we are not as harsh as SO we still prefer a starting point as well. What have you tried?



  • @fcarney Hi thanks for pointing it out. I understand what you are saying, but this question is not about the help with the code but rather about the general direction of what to choose as I find the amount of documentation about QtConcurrent and QThreadPool to be quite incomplete.



  • When I get stuck I build something. See what works. I have a repo dedicated to things I test out at work. Then when I figure it out I have a huge collection of examples of how to do things (and someones how not to do). I get you are at the middle point, not sure where to start. You may end up having to do a process of elimination.



  • @fcarney Yeah, I am also very new to C++ and Qt and I am also kind of bound by time. In the long run I will follow the same approach as you. Thanks for the suggestion, and yes I agree, knowing "How not to do it" is very helpful :)


  • Moderators

    @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