簡體   English   中英

線程池C ++

[英]Thread Pool C++

我有以下for循環:

for (int i = 0; i < 100; i++) {
    someJob();
}

我想只用5個線程運行這個函數,我該怎么辦?

我嘗試的是使用5個線程創建數組,如果索引等於5以等待所有線程再次使用它,但我確信還有另一種方法可以做到這一點:

std::thread t[THREAD_COUNT];
int j=0;

 for (int i = 0; i < 100; i++) {
    t[j++] = std::thread(someJob);
    if (j == THREAD_COUNT)
    {
        for (int k = 0; k < THREAD_COUNT; k++)
        {
            if (t[k].joinable())
                t[k].join();
        }
        j = 0;
    }
}

有什么建議嗎? (我不能用boost)

謝謝!

你可以簡單地使用std::async

如果要在5個不同的異步操作中執行此函數100次,則每個異步函數將執行該函數20次:

std::vector<std::future> results;
results.reserve(5);
for (auto i = 0; i< 5 ;i++){
   results.emplace_back([]{
     for(auto j = 0; j < 20 ; j++){
       doSomeFunction();
     } 
   });
}

for (auto& f : results){
    f.get();
}

可以修改相同的代碼以使用naked std::thread

您可以創建一個函數來測試您的線程數組,以找到一個空的線程來運行每個連續的作業。 像這樣的東西:

// synchronized output to prevent interleaving of results
#define sync_out(m) do{std::ostringstream o; o << m << '\n'; std::cout << o.str();}while(0)

void someJob(int id)
{
    sync_out("thread: " << id);
}

template<typename Job>
void start_thread(std::vector<std::thread>& threads, Job&& job)
{
    // find an ended thread
    for(auto&& thread: threads)
    {
        if(thread.joinable()) // still running or waiting to join
            continue;

        thread = std::thread(job);
        return;
    }

    // if not wait for one
    for(auto&& thread: threads)
    {
        if(!thread.joinable()) // dead thread (not run or already joined)
            continue;

        thread.join();
        thread = std::thread(job);
        return;
    }
}

int main()
{

    std::vector<std::thread> threads(5); // 5 threads

    for(int i = 0; i < 100; i++)
        start_thread(threads, [=]{someJob(i);});

    // wait for any unfinished threads    
    for(auto&& thread: threads)
        if(thread.joinable())
            thread.join();
}

您應該使用線程池

具體來說,您可以使用C ++線程池庫CPTL ,您的代碼將如下所示:

ctpl::thread_pool p(2 /* two threads in the pool */);

for (int i = 0; i < 100; i++) {
    p.push(someJob, "additional_param");
}

這是在運行中實現線程池的一種方法,同時保持安全。

#include <thread>
#include <vector>
#include <algorithm>
#include <mutex>

void someJob() { /* some lengthy process */ }

int main()
{
    const size_t THREAD_COUNT = 5;
    std::vector<std::thread> threadPool;
    std::mutex mtx;               // to block access to the pool

    for (int i = 0; i < 100; i++) 
    {
        {
            // add new thread to the pool.
            std::lock_guard<std::mutex> lock(mtx);
            threadPool.emplace_back(std::thread([&mtx, &threadPool]()
            {
                someJob();

                // task is done, remove thread from pool
                std::lock_guard<std::mutex> lock(mtx);
                threadPool.erase(
                    std::find_if(threadPool.begin(), threadPool.end(), 
                    [](std::thread& x) 
                    { 
                        if (x.get_id() == std::this_thread::get_id())
                        {
                            x.detach();  // have to call detach, since we can't 
                            return true; // destroy an attached thread.
                        }
                        return false; 
                    })
                );
            }));
        }

        for (;;)
        {
            // wait for a slot to be freed.
            std::this_thread::yield();
            std::lock_guard<std::mutex> lock(mtx);
            if (threadPool.size() < THREAD_COUNT)
            {
                break;
            }
        }
    }

    // wait for the last tasks to be done
    for (;;)
    {
        std::this_thread::yield();
        std::lock_guard<std::mutex> lock(mtx); // works fine without.. but...
        if (threadPool.empty())                // <-- can't call join here, since detached 
        {                                      // threads are not joinable()
            break;
        }
    }
    return 0;
}

OpenMP將允許您輕松地執行此操作,同時隱藏整個線程池。 大多數編譯器都有內置支持,但請參閱手冊以了解具體選項。 (gcc只需要傳遞-fopenmp作為選項)。

#pragma omp parallel for num_threads(5)
for (int i = 0; i < 100; i++) {
    someJob(i);
}

然后將你的工作分成5個線程。 如果省略num_threads(5) ,它將選擇多個線程。

暫無
暫無

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

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