Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Simple threading issue, need help!
Forum Updated to NodeBB v4.3 + New Features

Simple threading issue, need help!

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 5 Posters 2.0k Views 4 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    bdmontz
    wrote on last edited by
    #1

    I have spent the last 48 hours working on trying to get ANY multithreaded program working. I have scoured every resource, tried every method I can find (subclassing QThread, Worker/QThread, QConcurrent) I've copy pasted code directly from tutorials into new projects, nothing works. Either it doesn't work at all, QThread::isFinished() is always true and crashes at the end of the program (even though the thread is connected to the Workers "finish" signal which is emitted upon completion) or it runs completely serially.

    Using QElapsed timer I was watching the time to process threads. Processing a task on an array X wide, without threads it took 180 ms, with the array divided equally between 2 threads it took 210 ms, with just 1/2 width and running one thread is too 90 ms. These are the results I am getting constantly, even though QThread::idealThreadCount() returns 12, and I am on a beast of a computer.

    I followed VoidRealms example to the letter here
    https://www.youtube.com/watch?v=fd_SpePyWyI&index=125&list=PL2D1942A4688E9D63

    and while his output was nearly instant, my result was struggling to chug along and took a while to finish.

    I don't know what else to do, so I turn to you guys. If you can't help me get it working I'm going to stop trying to thread. I'm convinced either Qt Creator is broken, my PC is somehow limiting it, or god just hates me.

    Could someone give me some test code that definitely works and shows a serial process vs a parallel process performance so I can verify my system is broken?

    All I want is to split a QByteArray into chunks and convert it into an integer array to reduce a 500 ms process into sub 100ms, and I've sunk way too much time into this. Please help.

    B M 2 Replies Last reply
    0
    • B bdmontz

      I have spent the last 48 hours working on trying to get ANY multithreaded program working. I have scoured every resource, tried every method I can find (subclassing QThread, Worker/QThread, QConcurrent) I've copy pasted code directly from tutorials into new projects, nothing works. Either it doesn't work at all, QThread::isFinished() is always true and crashes at the end of the program (even though the thread is connected to the Workers "finish" signal which is emitted upon completion) or it runs completely serially.

      Using QElapsed timer I was watching the time to process threads. Processing a task on an array X wide, without threads it took 180 ms, with the array divided equally between 2 threads it took 210 ms, with just 1/2 width and running one thread is too 90 ms. These are the results I am getting constantly, even though QThread::idealThreadCount() returns 12, and I am on a beast of a computer.

      I followed VoidRealms example to the letter here
      https://www.youtube.com/watch?v=fd_SpePyWyI&index=125&list=PL2D1942A4688E9D63

      and while his output was nearly instant, my result was struggling to chug along and took a while to finish.

      I don't know what else to do, so I turn to you guys. If you can't help me get it working I'm going to stop trying to thread. I'm convinced either Qt Creator is broken, my PC is somehow limiting it, or god just hates me.

      Could someone give me some test code that definitely works and shows a serial process vs a parallel process performance so I can verify my system is broken?

      All I want is to split a QByteArray into chunks and convert it into an integer array to reduce a 500 ms process into sub 100ms, and I've sunk way too much time into this. Please help.

      B Offline
      B Offline
      bdmontz
      wrote on last edited by kshegunov
      #2

      I'll add some code so you can see what I'm doing.

      Here is the code that is the same as VoidRealms. It is so slow in comparison, while running on an i7-3930k @ 3.20GHz.
      Here is a gif of it running
      Here is a .gif showing it's slow operation. http://i.imgur.com/lgt3cPZ.gifv

      Dialog.h

      #ifndef DIALOG_H
      #define DIALOG_H
      
      #include <QDialog>
      #include <QDebug>
      #include <QtConcurrent>
      
      
      namespace Ui {
      class Dialog;
      }
      
      class Dialog : public QDialog
      {
          Q_OBJECT
      
      public:
          explicit Dialog(QWidget *parent = 0);
          ~Dialog();
      
          static int getNumber(int &baseNumber);
      
      private slots:
          void on_pushButton_clicked();
      
      private:
          Ui::Dialog *ui;
      };
      
      #endif // DIALOG_H
      

      Dialog.cpp

      #include "dialog.h"
      #include "ui_dialog.h"
      
      Dialog::Dialog(QWidget *parent) :
          QDialog(parent),
          ui(new Ui::Dialog)
      {
          ui->setupUi(this);
          qDebug() << QThread::idealThreadCount();
      }
      
      Dialog::~Dialog()
      {
          delete ui;
      }
      
      int Dialog::getNumber(int &baseNumber)
      {
          int high = 10000;
          int low = 1;
          int random = qrand() % ((high + 1) - low) + low;
      
          qDebug() << "Randomizing " << baseNumber << " = " << random;
          baseNumber = random;
      
          return 0;
      }
      
      void Dialog::on_pushButton_clicked()
      {
          QList<int> list;
          //Add 0 to 99 to list
          for(int i =0; i<100;i++)
          {
              list.append(i);
          }
      
          //block until all have completed
          QtConcurrent::blockingMap(list,&Dialog::getNumber);
      
          ui->listWidget->clear();
      
          //update the ui
          for(int i = 0; i<list.count(); i++)
          {
              ui->listWidget->addItem(QString::number(i) + " = " + QString::number(list.at(i)));
          }
      }
      

      Main

      #include "dialog.h"
      #include <QApplication>
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          Dialog w;
          w.show();
      
          return a.exec();
      }
      
      jsulmJ 1 Reply Last reply
      0
      • B bdmontz

        I'll add some code so you can see what I'm doing.

        Here is the code that is the same as VoidRealms. It is so slow in comparison, while running on an i7-3930k @ 3.20GHz.
        Here is a gif of it running
        Here is a .gif showing it's slow operation. http://i.imgur.com/lgt3cPZ.gifv

        Dialog.h

        #ifndef DIALOG_H
        #define DIALOG_H
        
        #include <QDialog>
        #include <QDebug>
        #include <QtConcurrent>
        
        
        namespace Ui {
        class Dialog;
        }
        
        class Dialog : public QDialog
        {
            Q_OBJECT
        
        public:
            explicit Dialog(QWidget *parent = 0);
            ~Dialog();
        
            static int getNumber(int &baseNumber);
        
        private slots:
            void on_pushButton_clicked();
        
        private:
            Ui::Dialog *ui;
        };
        
        #endif // DIALOG_H
        

        Dialog.cpp

        #include "dialog.h"
        #include "ui_dialog.h"
        
        Dialog::Dialog(QWidget *parent) :
            QDialog(parent),
            ui(new Ui::Dialog)
        {
            ui->setupUi(this);
            qDebug() << QThread::idealThreadCount();
        }
        
        Dialog::~Dialog()
        {
            delete ui;
        }
        
        int Dialog::getNumber(int &baseNumber)
        {
            int high = 10000;
            int low = 1;
            int random = qrand() % ((high + 1) - low) + low;
        
            qDebug() << "Randomizing " << baseNumber << " = " << random;
            baseNumber = random;
        
            return 0;
        }
        
        void Dialog::on_pushButton_clicked()
        {
            QList<int> list;
            //Add 0 to 99 to list
            for(int i =0; i<100;i++)
            {
                list.append(i);
            }
        
            //block until all have completed
            QtConcurrent::blockingMap(list,&Dialog::getNumber);
        
            ui->listWidget->clear();
        
            //update the ui
            for(int i = 0; i<list.count(); i++)
            {
                ui->listWidget->addItem(QString::number(i) + " = " + QString::number(list.at(i)));
            }
        }
        

        Main

        #include "dialog.h"
        #include <QApplication>
        
        int main(int argc, char *argv[])
        {
            QApplication a(argc, argv);
            Dialog w;
            w.show();
        
            return a.exec();
        }
        
        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on last edited by
        #3

        @bdmontz Here I can see that you print out the values: http://i.imgur.com/lgt3cPZ.gifv
        You should measure the execution time without printing values, because printing values is an expensive operation.
        And you should use a much bigger list, 100 elements is not really worth using multi-threading.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        1
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi,

          To add to @jsulm, if you want to get most of the performance you can from your code you should also take care of what container you use, how you access them, and how you construct your data. For example use QVector or std::vector rather than QList. Use a const iterator to go through your container, optimize your string building code etc.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • B bdmontz

            I have spent the last 48 hours working on trying to get ANY multithreaded program working. I have scoured every resource, tried every method I can find (subclassing QThread, Worker/QThread, QConcurrent) I've copy pasted code directly from tutorials into new projects, nothing works. Either it doesn't work at all, QThread::isFinished() is always true and crashes at the end of the program (even though the thread is connected to the Workers "finish" signal which is emitted upon completion) or it runs completely serially.

            Using QElapsed timer I was watching the time to process threads. Processing a task on an array X wide, without threads it took 180 ms, with the array divided equally between 2 threads it took 210 ms, with just 1/2 width and running one thread is too 90 ms. These are the results I am getting constantly, even though QThread::idealThreadCount() returns 12, and I am on a beast of a computer.

            I followed VoidRealms example to the letter here
            https://www.youtube.com/watch?v=fd_SpePyWyI&index=125&list=PL2D1942A4688E9D63

            and while his output was nearly instant, my result was struggling to chug along and took a while to finish.

            I don't know what else to do, so I turn to you guys. If you can't help me get it working I'm going to stop trying to thread. I'm convinced either Qt Creator is broken, my PC is somehow limiting it, or god just hates me.

            Could someone give me some test code that definitely works and shows a serial process vs a parallel process performance so I can verify my system is broken?

            All I want is to split a QByteArray into chunks and convert it into an integer array to reduce a 500 ms process into sub 100ms, and I've sunk way too much time into this. Please help.

            M Offline
            M Offline
            mjsurette
            wrote on last edited by
            #5

            @bdmontz
            I dropped your dialog.cpp into the voidrealms code that I had downloaded from his website. It just zipped along. I have no timinig results, but there was no discernible delay. Strange indeed.

            Your timing results reminded me of a YouTube video by Scott Myers on cpu caches and false sharing. https://www.youtube.com/watch?v=WDIkqP4JbkE It's over an hour long but I think that it may answer your question about scalability.

            Mike

            kshegunovK 1 Reply Last reply
            0
            • M mjsurette

              @bdmontz
              I dropped your dialog.cpp into the voidrealms code that I had downloaded from his website. It just zipped along. I have no timinig results, but there was no discernible delay. Strange indeed.

              Your timing results reminded me of a YouTube video by Scott Myers on cpu caches and false sharing. https://www.youtube.com/watch?v=WDIkqP4JbkE It's over an hour long but I think that it may answer your question about scalability.

              Mike

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by kshegunov
              #6

              @mjsurette said in Simple threading issue, need help!:

              Your timing results reminded me of a YouTube video by Scott Myers on cpu caches and false sharing.

              This is not even remotely related. Consider the function that's executed by each thread:

              int Dialog::getNumber(int &baseNumber)
              {
                  // These 3 lines expand to about 5 asm instructions after the compiler optimizes out the constants (they're smart that way).
                  int high = 10000;
                  int low = 1;
                  int random = qrand() % ((high + 1) - low) + low;
              
                  // This is an IO operation
                  qDebug() << "Randomizing " << baseNumber << " = " << random;
                 
                  baseNumber = random;  // This is a single mov instruction at best
              
                  return 0;
              }
              

              IO operations are inherently serial, you can't thread them, which means that whatever number of threads you start their writing to the file will be serialized (I'm talking low-level here, not even under your control). To pile up not only will the scheduler have to switch contexts for the writing giving time slots for each thread to write to the file, but also IO operations are slow. By slow I mean terribly slow compared to the function call, and addition instructions the compiler will generate for the first part of the function.

              Think it this way: He's measuring how much the ocean level drops if you fill a cup of water from it ...

              Read and abide by the Qt Code of Conduct

              M 1 Reply Last reply
              1
              • kshegunovK kshegunov

                @mjsurette said in Simple threading issue, need help!:

                Your timing results reminded me of a YouTube video by Scott Myers on cpu caches and false sharing.

                This is not even remotely related. Consider the function that's executed by each thread:

                int Dialog::getNumber(int &baseNumber)
                {
                    // These 3 lines expand to about 5 asm instructions after the compiler optimizes out the constants (they're smart that way).
                    int high = 10000;
                    int low = 1;
                    int random = qrand() % ((high + 1) - low) + low;
                
                    // This is an IO operation
                    qDebug() << "Randomizing " << baseNumber << " = " << random;
                   
                    baseNumber = random;  // This is a single mov instruction at best
                
                    return 0;
                }
                

                IO operations are inherently serial, you can't thread them, which means that whatever number of threads you start their writing to the file will be serialized (I'm talking low-level here, not even under your control). To pile up not only will the scheduler have to switch contexts for the writing giving time slots for each thread to write to the file, but also IO operations are slow. By slow I mean terribly slow compared to the function call, and addition instructions the compiler will generate for the first part of the function.

                Think it this way: He's measuring how much the ocean level drops if you fill a cup of water from it ...

                M Offline
                M Offline
                mjsurette
                wrote on last edited by
                #7

                @kshegunov

                Thanks, somehow I skipped over the qDebug() in there and the effect it would have.

                Mike

                1 Reply Last reply
                0

                • Login

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved