Extend the life of threads with synchronization (C++11)

后端 未结 4 1330
不知归路
不知归路 2020-12-08 03:17

I have a program with a function which takes a pointer as arg, and a main. The main is creating n threads, each of them running the function on different me

4条回答
  •  囚心锁ツ
    2020-12-08 03:37

    The following is a simple compiling and working code performing some random stuffs. It implements aleguna's concept of barrier. The task length of each thread is different so it is really necessary to have a strong synchronization mechanism. I will try to do a pool on the same tasks and benchmark the result, and then maybe with futures as pointed out by Andy Prowl.

    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    const unsigned int n_threads=4; //varying this will not (almost) change the total amount of work
    const unsigned int task_length=30000/n_threads;
    const float task_length_variation=task_length/n_threads;
    unsigned int rep=1000; //repetitions of tasks
    
    class t_chronometer{
     private: 
      std::chrono::steady_clock::time_point _t;
    
     public:
      t_chronometer(): _t(std::chrono::steady_clock::now()) {;}
      void reset() {_t = std::chrono::steady_clock::now();}
      double get_now() {return std::chrono::duration_cast>(std::chrono::steady_clock::now() - _t).count();}
      double get_now_ms() {return 
          std::chrono::duration_cast>(std::chrono::steady_clock::now() - _t).count();}
    };
    
    class t_barrier {
     private:
       std::mutex m_mutex;
       std::condition_variable m_cond;
       unsigned int m_threshold;
       unsigned int m_count;
       unsigned int m_generation;
    
     public:
       t_barrier(unsigned int count):
        m_threshold(count),
        m_count(count),
        m_generation(0) {
       }
    
       bool wait() {
          std::unique_lock lock(m_mutex);
          unsigned int gen = m_generation;
    
          if (--m_count == 0)
          {
              m_generation++;
              m_count = m_threshold;
              m_cond.notify_all();
              return true;
          }
    
          while (gen == m_generation)
              m_cond.wait(lock);
          return false;
       }
    };
    
    
    using namespace std;
    
    void do_something(complex * c, unsigned int max) {
      complex a(1.,0.);
      complex b(1.,0.);
      for (unsigned int i = 0; i * c, unsigned int max, t_barrier* start_barrier, t_barrier* end_barrier) {
      while (!done) {
        start_barrier->wait ();
        do_something(c,max);
        end_barrier->wait ();
      }
      cout << "task finished" << endl;
    }
    
    int main() {
      t_chronometer t;
    
      std::default_random_engine gen;
      std::normal_distribution dis(.0,1000.0);
    
      complex cpx[n_threads];
      for (unsigned int i=0; i < n_threads; i++) {
        cpx[i] = complex(dis(gen), dis(gen));
      }
    
      t_barrier start_barrier (n_threads + 1); // child threads + main thread
      t_barrier end_barrier (n_threads + 1); // child threads + main thread
    
      std::thread mythread[n_threads];
      unsigned long int sum=0;
      for (unsigned int i=0; i < n_threads; i++) {
        unsigned int max = task_length +  i * task_length_variation;
        cout << i+1 << "th task length: " << max << endl;
        mythread[i] = std::thread(task, &cpx[i], max, &start_barrier, &end_barrier);
        sum+=max;
      }
      cout << "total task length " << sum << endl;
    
      complex c(0,0);
      for (unsigned long int j=1; j < rep+1; j++) {
        start_barrier.wait (); //give to the threads the missing call to start
        if (j==rep) done=true;
        end_barrier.wait (); //wait for the call from each tread
        if (j%100==0) cout << "cycle: " << j << endl;
        for (unsigned int i=0; i

提交回复
热议问题