代码之家  ›  专栏  ›  技术社区  ›  William Miller devops-admin

将子线程同步到父线程管理的原子时

  •  0
  • William Miller devops-admin  · 技术社区  · 7 年前

    我正在尝试编写一个模拟,其中不同的线程需要根据父线程管理的原子模拟时间在特定于线程的时间间隔(在这里的最小示例中,时间间隔在1到4之间)上执行给定的计算。


    确切地

    #include <thread>
    #include <iostream>
    #include <atomic>
    
    std::atomic<int> simTime;
    std::atomic<int> tocalc;
    int end = 10000;
    
    void threadFunction(int n);
    
    int main() {
      int nthreads = 4;
      std::thread threads[nthreads];
      for (int ii = 0; ii < nthreads; ii ++) {
        threads[ii] = std::thread(threadFunction, ii+1);
      }
    
      simTime = 0;
      tocalc = 0;
      while (simTime < end) {
        tocalc = nthreads - 1;
        simTime += 1;
        // do calculation
        while (tocalc > 0) {
          // wait until all the threads have done their calculation
          // or at least checked to see if they need to
        }
      }
    
      for (int ii = 0; ii < nthreads; ii ++) {
        threads[ii].join();
      }
    }
    
    void threadFunction(int n) {
      int prev = simTime;
      int fix = prev;
      int ncalcs = 0;
      while (simTime < end) {
        if (simTime - prev > 0) {
          prev = simTime;
          if (simTime - fix >= n) {
            // do calculation
            ncalcs ++;
            fix = simTime;
          }
          tocalc --;
        }
      }
      std::cout << std::to_string(n)+" {ncalcs} - "+std::to_string(ncalcs)+"\n";
    }
    

    然而,输出与预期不一致,一种可能的输出是

    2 {ncalcs} - 4992
    1 {ncalcs} - 9983
    3 {ncalcs} - 3330
    4 {ncalcs} - 2448
    

    2 {ncalcs} - 5000
    1 {ncalcs} - 10000
    3 {ncalcs} - 3333
    4 {ncalcs} - 2500
    

    我想知道是否有人知道为什么这种强迫线程等待下一步的方法似乎失败了——如果这可能是我的代码的一个简单问题,或者是这种方法的一个更基本的问题。任何洞察都将不胜感激,谢谢。


    我使用这种方法是因为我尝试过的其他方法(例如使用 pipes

    2 回复  |  直到 7 年前
        1
  •  1
  •   William Miller devops-admin    6 年前

    要展开注释,请初始化 tocalc nthreads - 1 一些 所有子线程的迭代次数都将减少 在父线程对其求值之前-读取和写入 atomic

    • 儿童1减量 托卡尔
    • 托卡尔 ,新值为1
    • 托卡尔 ,新值为0
    • 儿童2减量 托卡尔 ,新值为-1
    • tocalc > 0 ,返回false-模拟进度

    其他时候,可以在最后一个线程减量之前安排父级求值 托卡尔

    • 儿童1减量 ,新值为2
    • 儿童3减量 ,新值为1
    • 托卡尔 ,新值为0
    • 父级评估是否 ,返回false-模拟进度
    • 儿童2减量 ,新值为2

    在这种情况下,子线程2将错过一次迭代。由于调度顺序的半随机性,这种情况并非每次都会发生,因此未命中的总数不是线程数的线性函数,而是总迭代次数的一小部分。如果将代码修改为下面的值,则会产生所需的结果。

    #include <thread>
    #include <iostream>
    #include <atomic>
    
    std::atomic<int> simTime;
    std::atomic<int> tocalc;
    int end = 10000;
    
    void threadFunction(int n);
    
    int main() {
        int nthreads = 4;
        simTime = 0;
        tocalc = 0;
        std::thread threads[nthreads];
        for (int ii = 0; ii < nthreads; ii ++) {
            threads[ii] = std::thread(threadFunction, ii+1);
        }
    
        int wait = 0;
        while (simTime < end) {
            tocalc = nthreads;
            simTime += 1;
            // do calculation
            while (tocalc > 0) {
                // wait until all the threads have done their calculation
                // or at least checked to see if they need to
            }
        }
        for (int ii = 0; ii < nthreads; ii ++) {
            threads[ii].join();
        }
    }
    
    void threadFunction(int n) {
        int prev = 0;
        int fix = prev;
        int ncalcs = 0;
        while (simTime < end) {
            if (simTime - prev > 0) {
                prev = simTime;
                if (simTime - fix >= n) {
                    // do calculation
                    ncalcs ++;
                    fix = simTime;
                }
                tocalc --;
            }
        }
        std::cout << std::to_string(n)+" {ncalcs} - "+std::to_string(ncalcs)+"\n";
    }
    

    2 {ncalcs} - 5000
    3 {ncalcs} - 3333
    1 {ncalcs} - 10000
    4 {ncalcs} - 2500
    
        2
  •  0
  •   user10729329 user10729329    7 年前

    使用类似的设置,我注意到并不是每个线程都能达到您期望的数量,而是只差一个线程。即

    2 {ncalcs} - 4999
    4 {ncalcs} - 2500
    1 {ncalcs} - 9999
    3 {ncalcs} - 3333
    

    或者诸如此类,就线程和线程数而言似乎是随机的。虽然我不确定是什么原因造成的,但我认为发出警告可能是好的,你可以通过检查 simTime - fix == 0

    推荐文章