【问题标题】:wait for results in loop with ordering通过排序等待结果循环
【发布时间】:2020-07-17 19:21:36
【问题描述】:

尝试并行化计算方法,然后等待从所有计算中收集结果并将它们与其他数据注入一起存储在 std::list 中,因此看不到性能提升。也许如果我知道'num_results',我可以通过锁定(互斥)写入(push_back)过程以某种方式合并两个周期并将数据存储在列表中?另一件事是如何保持顺序(如果在某些 [i] 上计算速度很快) 在一个内核的一个周期中这样做太慢了。

// here is pseudocode 

void SomeClass::SomeMethod() {
  size_t num_results = request_list.size();
  std::list<result_t> some_results;
  float *result = new float[num_results];
  // linearly I do one for in where one parameter of list pushing are long computing function
  // so I create array of function results and try to store data same time then wait and collect in list with other data
  for (size_t i(0); i < num_results; i++) {
     // Calculate is hard function and may vary in times depending on imput
     // use temporary thread object and labda function to acces class members data
     thread t([&]() { result[i] = Calculate(request_list[i]); });
     // where or how to wait for all results stored in array only then push them to list?

     t.join(); // where or how to wait for all result[] for next cycle or merge both? 
  } 
  // conjugate result with some other data from static list with same id's
  for (std::size_t i(0); i < num_requests; i++) {
      some_results.push_back( result_t(result[i], other_data[i], ...) );
  }

  delete [] result; // free memory

   // Continue job with some_results list

}

我的并行操作是不是错了?

【问题讨论】:

    标签: c++ multithreading asynchronous std


    【解决方案1】:

    再看join函数,你启动一个计算线程,等待那个线程,然后再启动另一个线程。相反,您应该启动多个线程并在之后加入它们。您的操作顺序错误,因为您等待每个线程。

    http://www.cplusplus.com/reference/thread/thread/join/

    【讨论】:

    • 如果它处于循环状态,我该如何进行连接?
    • 你需要在循环之前创建线程并在之后加入它们
    • 那么可能会使用具有固定数量线程的线程池。但它更难实现,你可能需要一个库来实现它
    • 我找到了解决方案,调用 calc 方法作为 std::async 的参数并将它们推送到 std::list 然后在循环等待该期货列表的有效方法并弹出它们来自未来列表并同时添加到结果向量中。现在它瞬间运行。也似乎 auto f = [&]() { return Calc;然后将 f 作为 std::async 的参数传递比直接传递效果更好,不知道为什么 lambda 函数会死掉而不是线程启动,这是向上代码中的 UB 问题之一。
    【解决方案2】:
    // solution for dynamic async threads with store results 
    // after lots of documentation reading of multithreading
    // function do asynchronic calls of N count of heavy ops then waits in idle 
    // cycle to aquire all results, if first is ready push it to vector
    // while it waits for first result accesible, next maybe ready allready    
    
    
    void SomeClass::SomeMethod() {
       auto request_util = [&](std::size_t i) { return Calculate(i); };
       size_t num_results = request_list.size();
       std::list<std::future<float>> request_respond_list;
       for (std::size_t i(0); i < num_requests; i++)
          request_respond_list.push_back( std::async(std::launch::async, request_util, i));
    
       std::size_t id(0);
    
       // example of result storing
       // float *result = new float[num_results];
       std::vector< result_t > results;
       while (!request_respond_list.empty()) {
          if (request_respond_list.front().valid()) {
              results.push_back(result_t(request_respond_list.front().get(), other_data[id]));
              request_respond_list.pop_front();
              id++;
          } else
             std::this_thread::yield();
       } request_respond_list.clear();
    
      // do other job with results vector
       ....
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-16
      • 2021-11-20
      • 2020-10-21
      • 2021-10-30
      • 2021-09-10
      相关资源
      最近更新 更多