簡體   English   中英

C++線程池中的線程執行順序

[英]C++ Thread execution order in a thread pool

有誰知道 C++ 線程池實現,它既允許並行線程(如典型的線程池),又允許背靠背串行執行順序。 我花了幾天時間試圖通過修改以下 線程池來完成這項工作,但我似乎無法讓它工作。 我研究了英特爾 TBB 使用的技術,也研究了可能使用微軟 PPL 的概念(它的異步代理庫看起來很有希望)——兩者都有面向任務的技術來實現上述目標——不幸的是,這些解決方案將不工作我的目標 PowerPC linux 嵌入式目標。

編輯我將一個實時的coliru演示與生成線程圖的源代碼放在一起 - 並且還展示了一個很好的scheduler_loop示例,理論上可以等待線程完成。 該代碼還顯示了一個帶有 2 個線程的 UtlThreadPool,我在其中向它提供並發任務 - 但是“饋送”並不完全正確,需要做一些工作才能遍歷節點。

我用來制作執行圖的數據結構如下所示。 它使用PriorityNode數據結構。 這個結構本質上是一個 PriorityNode 的鏈表,每一個都包含一個可以並發運行的PriorityLevel任務向量和一個指向下一個 PriorityNode 的指針,該指針指示之后要串行運行的線程。 一旦這些都完成了,如果 mNextNode 成員不是 nullptr,那么這應該被安排在線程池中運行(依此類推,直到 mNextNode 為 nullptr。通過這個 PriorityNodes 鏈表進行排序是我想要線程的方式池以通過其線程進行排序。PriorityNode 具有插入運算符,通常會產生如下輸出。(這意味着 1A1 可以與 1A2 並發運行,當這兩個線程都完成后,下一個 PriorityNode 將允許 1B1、1B2、1B3 和1B4 並發運行 - 無論池中有多少線程可用。

1A1
1A2
+-1B1
+-1B2
+-1B3
+-1B4

我似乎解決這個問題的最接近的東西 - 再次注意它是特定於英特爾的,我在電源 PC 上是英特爾 TBB - 是他們用於串行執行順序的示例。

/**
 * Branch representing fundamental building block of
 * a priority tree containing szPriority entries.<p>
 *
 * Each priority tree struct contains a vector of concurrent
 * priorities that can be scheduled to run in the thread pool -
 * note that the thread pool must have no entries associated
 * with the current channel running before enqueueing these
 * tasks. The application must wait for the thread pool to
 * complete these tasks before queuing up the dependent tasks
 * described in the mNextNode smart pointer. If mNextNode is
 * unassigned (nullptr), then we have reached the end of the
 * tree.
 */
struct PriorityNode {
    explicit PriorityNode(
        const std::vector<PriorityLevel>& rConcurrent,
        const std::shared_ptr<PriorityNode>& rNext = std::shared_ptr<PriorityNode>(),
        const size_t& rDepth = 0)
        : mConcurrent(rConcurrent)
        , mNextNode(rNext)
        , mDepth(rDepth)
    {}

    /**
    * Stream insert operator<p>
    *
    * @param os     [in,out] output stream
    * @param rhs    [in] PriorityLevel to send to the output
    *               stream.
    *
    * @return a reference to the updated stream
    */
    inline friend std::ostream& operator << (
        std::ostream& os, const PriorityNode& rhs) {
        // indent 2 spaces per depth level
        std::string indent = rhs.mDepth > 0 ?
            (std::string("+") +
            std::string((rhs.mDepth * 2) - 1, '-')) :
            std::string();
        // print out the concurrent threads that 
        // can be scheduled with the thread pool
        for (const auto& next : rhs.mConcurrent) {
            os << indent << next << std::endl;
        }
        // print the dependent priorities that can only
        // be scheduled when the concurrent ones are finished
        if (rhs.mNextNode) {
            os << *rhs.mNextNode << std::endl;
        }
        return os;
    }
    // these are all equivalent thread priorities
    // that can be run simultaneously
    std::vector<PriorityLevel> mConcurrent;

    // these are concurrent threads that must be AFTER all 
    // mConcurrent tasks have completed (exiting the thread pool)
    std::shared_ptr<PriorityNode> mNextNode;

    // recursion depth
    size_t mDepth;
};

為什么不在 PowerPC 上使用 TBB? 它是一個高度可移植的庫,旨在盡可能地跨平台; 我聽說它正在被 TBB 開源社區移植到 BlueGen 上。 您可以在英特爾 TBB 論壇上提問,例如,恢復此論壇主題

Intel 不會為 TBB 分發 PowerPC 二進制文件,但您可以嘗試從源代碼構建它

做tbb

另請參閱這些社區補丁

如果有人仍在尋找這個,請查看這里的 repo - https://github.com/hirak99/ordered_thread_pool

基本上用這個你可以替換這樣的代碼 -

while (...) {
  std::cout << CostlyFn(input)) << std::endl;
}

進入這個——

OrderedThredPool<std::string> pool{10, 1};
while (...) {
  pool.Do(
    [&input] { return CostlyFn(input); },
    [](const std::string& out) {
      std::cout << out << std::endl;
    });
}

它將按順序執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM