সি ++ 11 এ থ্রেড পুলিং


130

প্রাসঙ্গিক প্রশ্ন :

সি ++ 11 সম্পর্কে:

বুস্ট সম্পর্কে:


আমি পেতে পারি থ্রেডের পুকুর থেকে কার্যগুলিকে পাঠাতে তৈরি এবং তাদের বারবার মুছে? এর অর্থ যোগ না দিয়ে পুনরায় সংশ্লেষ করার জন্য অবিরাম থ্রেড।


আমার কাছে এমন কোড রয়েছে যা দেখতে দেখতে:

namespace {
  std::vector<std::thread> workers;

  int total = 4;
  int arr[4] = {0};

  void each_thread_does(int i) {
    arr[i] += 2;
  }
}

int main(int argc, char *argv[]) {
  for (int i = 0; i < 8; ++i) { // for 8 iterations,
    for (int j = 0; j < 4; ++j) {
      workers.push_back(std::thread(each_thread_does, j));
    }
    for (std::thread &t: workers) {
      if (t.joinable()) {
        t.join();
      }
    }
    arr[4] = std::min_element(arr, arr+4);
  }
  return 0;
}

প্রতিটি পুনরাবৃত্তিতে থ্রেড তৈরি এবং যোগদানের পরিবর্তে, আমি প্রতিটি কর্মের থ্রেডগুলিতে আমার কর্মের পাঠাতে পছন্দ করি এবং কেবল একবার এগুলি তৈরি করি।


1
এখানে একটি সম্পর্কিত প্রশ্ন এবং আমার উত্তর।
didierc

1
টিবিবি (এটি ইন্টেল, তবে ফ্রি ও ওপেন সোর্স, এবং আপনি যা চান ঠিক তেমনটি ব্যবহার করার বিষয়ে চিন্তা করেছেন: আপনি কেবল (পুনরাবৃত্তভাবে বিভাজ্য) কার্য জমা দিন এবং থ্রেডগুলি নিয়ে চিন্তা করবেন না)?
ওয়াল্টার

2
এই FOSS প্রকল্পটি আমার একটি থ্রেড পুল গ্রন্থাগার তৈরি করার চেষ্টা, আপনি চান কিনা তা পরীক্ষা করে দেখুন। -> code.google.com/p/threadpool11
Etherealone

টিবিবি ব্যবহারে সমস্যা কী?
ওয়াল্টার

উত্তর:


84

আপনি সি ++ থ্রেড পুল গ্রন্থাগার, https://github.com/vit-vit/ctpl ব্যবহার করতে পারেন ।

তারপরে আপনার লিখিত কোডটি নিম্নলিখিতগুলির সাথে প্রতিস্থাপন করা যেতে পারে

#include <ctpl.h>  // or <ctpl_stl.h> if ou do not have Boost library

int main (int argc, char *argv[]) {
    ctpl::thread_pool p(2 /* two threads in the pool */);
    int arr[4] = {0};
    std::vector<std::future<void>> results(4);
    for (int i = 0; i < 8; ++i) { // for 8 iterations,
        for (int j = 0; j < 4; ++j) {
            results[j] = p.push([&arr, j](int){ arr[j] +=2; });
        }
        for (int j = 0; j < 4; ++j) {
            results[j].get();
        }
        arr[4] = std::min_element(arr, arr + 4);
    }
}

আপনি পছন্দসই সংখ্যক থ্রেড পাবেন এবং পুনরাবৃত্তিতে এগুলি বারবার তৈরি এবং মুছবেন না।


11
এই উত্তর হওয়া উচিত; একক শিরোলেখ, পঠনযোগ্য, সোজা, সংক্ষিপ্ত এবং স্ট্যান্ডার্ড-কমপ্লায়েন্ট সি ++ 11 লাইব্রেরি। মহান কাজ!
জোনাথন এইচ

@ ভিট-ভিট আপনি কোনও ফাংশন দিয়ে উদাহরণ দিতে পারেন দয়া করে? আপনি একটি ধাক্কা না বর্গ সদস্য ফাংশনresults[j] = p.push([&arr, j](int){ arr[j] +=2; });
হানী জিওসি

1
@ হানিগক কেবল উল্লেখ হিসাবে উদাহরণটি ক্যাপচার করুন।
জোনাথন এইচ

@ ভিট-ভিট আপনাকে এসটিএল সংস্করণ উন্নত করার জন্য একটি টান অনুরোধ প্রেরণ করেছে।
জোনাথন এইচ

@ ভিট-ভিট: প্রশ্নগুলি, ইঙ্গিতের ইঙ্গিত সহ সেই লাইব্রেরির রক্ষণাবেক্ষণকারীটির সাথে যোগাযোগ করা কঠিন difficult
einpoklum

82

এটি আমার অনুরূপ অন্য একটি অনুরূপ পোস্টে অনুলিপি করা হয়েছে, আশা করি এটি সহায়তা করতে পারে:

1) কোনও সিস্টেম সমর্থন করতে পারে সর্বাধিক সংখ্যক থ্রেড দিয়ে শুরু করুন:

int Num_Threads =  thread::hardware_concurrency();

২) দক্ষ থ্রেডপুল প্রয়োগের জন্য, একবার নাম_থ্রেডস অনুসারে থ্রেড তৈরি হয়ে গেলে, নতুন তৈরি না করা বা পুরানোগুলি (যোগ দিয়ে) ধ্বংস না করাই ভাল। পারফরম্যান্স পেনাল্টি থাকবে, এমনকি আপনার অ্যাপ্লিকেশনটি সিরিয়াল সংস্করণের চেয়ে ধীর হয়ে যেতে পারে।

প্রতিটি সি ++ 11 থ্রেড তাদের ফাংশনটিতে একটি অসীম লুপ দিয়ে চলতে হবে, ক্রমাগত নতুন কাজের জন্য দখল এবং চালানোর জন্য অপেক্ষা করে।

থ্রেড পুলে এই জাতীয় ফাংশন কীভাবে সংযুক্ত করা যায় তা এখানে:

int Num_Threads = thread::hardware_concurrency();
vector<thread> Pool;
for(int ii = 0; ii < Num_Threads; ii++)
{  Pool.push_back(thread(Infinite_loop_function));}

3) অনন্ত_লুপ_ফানশন

টাস্কের সারিটির জন্য অপেক্ষা করা এটি "সময় (সত্য)" লুপ

void The_Pool:: Infinite_loop_function()
{
    while(true)
    {
        {
            unique_lock<mutex> lock(Queue_Mutex);

            condition.wait(lock, []{return !Queue.empty() || terminate_pool});
            Job = Queue.front();
            Queue.pop();
        }
        Job(); // function<void()> type
    }
};

4) আপনার কাতারে কাজ যুক্ত করার জন্য একটি ফাংশন করুন

void The_Pool:: Add_Job(function<void()> New_Job)
{
    {
        unique_lock<mutex> lock(Queue_Mutex);
        Queue.push(New_Job);
    }
    condition.notify_one();
}

5) আপনার কাতারে একটি স্বেচ্ছাসেবী ফাংশন বাঁধুন

Pool_Obj.Add_Job(std::bind(&Some_Class::Some_Method, &Some_object));

একবার আপনি এই উপাদানগুলি সংহত করার পরে, আপনার নিজস্ব গতিশীল থ্রেডিং পুল রয়েছে। এই থ্রেডগুলি সর্বদা চলবে, কাজের জন্য অপেক্ষা করছে।

কিছু সিনট্যাক্স ত্রুটি থাকলে আমি ক্ষমা চাইছি, আমি এই কোডগুলি টাইপ করেছি এবং আমার স্মৃতিশক্তি খারাপ আছে। দুঃখিত যে আমি আপনাকে সম্পূর্ণ থ্রেড পুল কোড সরবরাহ করতে পারি না, এটি আমার কাজের সততা লঙ্ঘন করবে।

সম্পাদনা করুন: পুলটি শেষ করতে, শাটডাউন () পদ্ধতিটি কল করুন:

XXXX::shutdown(){
{
    unique_lock<mutex> lock(threadpool_mutex);
    terminate_pool = true;} // use this flag in condition.wait

    condition.notify_all(); // wake up all threads.

    // Join all threads.
    for(std::thread &every_thread : thread_vector)
    {   every_thread.join();}

    thread_vector.clear();  
    stopped = true; // use this flag in destructor, if not set, call shutdown() 
}

থ্রেড (কনট থ্রেড &) = মুছলে আপনার কীভাবে ভেক্টর থাকে?
ক্রিস্টোফার পিজ

1
@ খ্রিস্টোফারপিজ std::vectorএর উপাদানগুলি অনুলিপিযোগ্য হওয়ার প্রয়োজন নেই। আপনি স্থানান্তর কেবল-প্রকার (সঙ্গে ভেক্টর ব্যবহার করতে পারেন unique_ptr, thread, future, ইত্যাদি)।
ড্যানিয়েল ল্যাঙ্গার

আপনার উপরের উদাহরণে, আপনি পুলটি কীভাবে বন্ধ করবেন? উচিত condition.waitএকটি পরিবর্তনশীল জন্য চেহারা stop_পরীক্ষক if (stop_ == true) { break;}?
জন

@ জন, দয়া করে উপরের শাটডাউন পদ্ধতিটি দেখুন।
পিএইচডি এপি ইইসি

2
শাটডাউন () এ, এটি থ্রেড_ভেক্টর.ক্রিয়ার () হওয়া উচিত; থ্রেড_ভেেক্টর.এম্পটি () এর পরিবর্তে; সঠিক?
সুধেরব্ব

63

থ্রেডের একটি পুলের অর্থ হল যে আপনার সমস্ত থ্রেড চলমান রয়েছে, সর্বদা - অন্য কথায় থ্রেড ফাংশনটি কখনই ফিরে আসে না। থ্রেডগুলিকে অর্থপূর্ণ কিছু করার জন্য আপনাকে উভয়ই থ্রেডকে কিছু করার আছে তা জানানোর পাশাপাশি প্রকৃত কাজের ডেটা যোগাযোগের উদ্দেশ্যে, আন্তঃ থ্রেড যোগাযোগের একটি সিস্টেম ডিজাইন করতে হবে।

সাধারণত এটি একরকমের যুগ্ম ডেটা কাঠামোকে জড়িত রাখবে এবং প্রতিটি থ্রেড সম্ভবত কিছুটা শর্ত পরিবর্তনশীলের উপর ঘুমাবে, যা কাজ করার সময় জানানো হবে। বিজ্ঞপ্তিটি পাওয়ার পরে, এক বা একাধিক থ্রেড জেগে উঠেছে, সমবর্তী ডেটা স্ট্রাকচার থেকে কোনও কাজ পুনরুদ্ধার করুন, এটি প্রক্রিয়া করুন এবং ফলটিকে অভিন্ন ফ্যাশনে সংরক্ষণ করুন।

এর পরে থ্রেডটি আরও কাজ করার দরকার আছে কিনা তা যাচাই করে নেবে এবং যদি ঘুমাতে ফিরে না যায়।

ফলশ্রুতিটি হ'ল আপনাকে এগুলি নিজেরাই ডিজাইন করতে হবে, যেহেতু সর্বজনীনভাবে প্রযোজ্য "কাজ" এর প্রাকৃতিক ধারণা নেই। এটি বেশ কিছুটা কাজ, এবং আপনার সঠিক হওয়াতে কিছু সূক্ষ্ম সমস্যা রয়েছে। (আপনি যদি এমন কোনও সিস্টেম পছন্দ করেন যা পর্দার আড়ালে আপনার জন্য থ্রেড পরিচালনার যত্ন নেয় তবে আপনি গোতে প্রোগ্রাম করতে পারেন))


11
"আপনাকে এগুলি নিজেই ডিজাইন করতে হবে" <- এটাই আমি এড়াতে চাইছি। গোরটাইনগুলি দুর্দান্ত মনে হচ্ছে।
ইয়াকতুল

2
@ ইয়াক্টুলা: আচ্ছা, এটি একটি অত্যন্ত অ-তুচ্ছ কাজ। আপনি কী ধরণের কাজ করতে চান তা আপনার পোস্ট থেকে এটিও পরিষ্কার নয় এবং এটি সমাধানের পক্ষে গভীরভাবে মৌলিক। আপনি গো ইন সি ++ বাস্তবায়ন করতে পারেন তবে এটি একটি খুব নির্দিষ্ট বিষয় হবে এবং অর্ধেক লোকেরা অভিযোগ করবে যে তারা কিছু আলাদা চায় want
কেরেক এসবি

19

একটি থ্রেডপুল মূলত ইভেন্ট লুপ হিসাবে কাজ করে এমন কোনও ফাংশনের সাথে আবদ্ধ সমস্ত থ্রেডের সেট। এই থ্রেডগুলি অবিরামভাবে কোনও কার্য সম্পাদনের জন্য বা তাদের নিজস্ব সমাপ্তির জন্য অপেক্ষা করবে।

থ্রেডপুল কাজটি চাকরি জমা দেওয়ার জন্য একটি ইন্টারফেস সরবরাহ করা, এই কাজগুলি চালনার নীতি (সময় নির্ধারণের নিয়ম, থ্রেড ইনস্ট্যান্টেশন, পুলের আকার) সংজ্ঞায়িত (এবং সম্ভবত সংশোধন) করা এবং থ্রেড এবং সম্পর্কিত সংস্থার অবস্থান নিরীক্ষণ করা।

সুতরাং বহুমুখী পুলের জন্য, একটি কাজটি কীভাবে চালু করা হয়, বাধাগ্রস্থ হয়, ফলাফল কী হয় (সেই প্রশ্নের জন্য প্রতিশ্রুতি এবং ভবিষ্যতের ধারণাটি দেখুন), থ্রেডগুলি কী ধরণের ইভেন্টগুলিতে প্রতিক্রিয়া জানাতে হবে তা নির্ধারণ করে একটি অবশ্যই শুরু করতে হবে কীভাবে, তারা কীভাবে এগুলি পরিচালনা করবে, কার্যগুলি দ্বারা পরিচালিত ইভেন্টগুলি থেকে কীভাবে এই ইভেন্টগুলিকে বৈষম্য করা হবে। আপনি দেখতে পাওয়ায় এটি বেশ জটিল হয়ে উঠতে পারে এবং থ্রেডগুলি কীভাবে কাজ করবে সে সম্পর্কে সীমাবদ্ধতা আরোপ করতে পারে, কারণ সমাধান আরও এবং আরও জড়িত হয়।

ইভেন্টগুলি পরিচালনা করার জন্য বর্তমান সরঞ্জামটি মোটামুটি বেয়ারবোনস (*): মুটিেক্সেস, শর্ত ভেরিয়েবল এবং তার উপরে কয়েকটি তাল (লকস, বাধা) এর মতো কয়েকটি বিমূর্ততা। তবে কিছু ক্ষেত্রে, এই বিস্মরণগুলি অযোগ্য হতে পারে (এই সম্পর্কিত প্রশ্নটি দেখুন ) এবং একটিকে অবশ্যই আদিম ব্যবহার করে ফিরে যেতে হবে।

অন্যান্য সমস্যাগুলিও পরিচালনা করতে হবে:

  • সংকেত
  • I / O
  • হার্ডওয়্যার (প্রসেসরের সম্পর্ক, ভিন্ন ভিন্ন সেটআপ)

এগুলি কীভাবে আপনার সেটিংয়ে খেলতে পারে?

অনুরূপ প্রশ্নের এই উত্তরটি একটি বিদ্যমান বাস্তবায়নকে নির্দেশ করে যা প্রচার এবং বৃদ্ধির উদ্দেশ্যে হয়।

আমি অন্য প্রশ্নের জন্য একটি থ্রেডপুলের খুব অশোধিত প্রয়োগের প্রস্তাব দিয়েছি , যা উপরে বর্ণিত অনেক সমস্যার সমাধান করে না। আপনি এটি তৈরি করতে চাইতে পারেন। অনুপ্রেরণা পেতে আপনি অন্য ভাষায় বিদ্যমান ফ্রেমওয়ার্কগুলি দেখতে চান।


(*) আমি একে সমস্যা হিসাবে দেখছি না, একেবারে বিপরীত। আমি মনে করি এটি সি ++ এর উত্তীর্ণ মনোভাব সি থেকে প্রাপ্ত ited


4
Follwoing [PhD EcE](https://stackoverflow.com/users/3818417/phd-ece) suggestion, I implemented the thread pool:

function_pool.h

#pragma once
#include <queue>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <cassert>

class Function_pool
{

private:
    std::queue<std::function<void()>> m_function_queue;
    std::mutex m_lock;
    std::condition_variable m_data_condition;
    std::atomic<bool> m_accept_functions;

public:

    Function_pool();
    ~Function_pool();
    void push(std::function<void()> func);
    void done();
    void infinite_loop_func();
};

function_pool.cpp

#include "function_pool.h"

Function_pool::Function_pool() : m_function_queue(), m_lock(), m_data_condition(), m_accept_functions(true)
{
}

Function_pool::~Function_pool()
{
}

void Function_pool::push(std::function<void()> func)
{
    std::unique_lock<std::mutex> lock(m_lock);
    m_function_queue.push(func);
    // when we send the notification immediately, the consumer will try to get the lock , so unlock asap
    lock.unlock();
    m_data_condition.notify_one();
}

void Function_pool::done()
{
    std::unique_lock<std::mutex> lock(m_lock);
    m_accept_functions = false;
    lock.unlock();
    // when we send the notification immediately, the consumer will try to get the lock , so unlock asap
    m_data_condition.notify_all();
    //notify all waiting threads.
}

void Function_pool::infinite_loop_func()
{
    std::function<void()> func;
    while (true)
    {
        {
            std::unique_lock<std::mutex> lock(m_lock);
            m_data_condition.wait(lock, [this]() {return !m_function_queue.empty() || !m_accept_functions; });
            if (!m_accept_functions && m_function_queue.empty())
            {
                //lock will be release automatically.
                //finish the thread loop and let it join in the main thread.
                return;
            }
            func = m_function_queue.front();
            m_function_queue.pop();
            //release the lock
        }
        func();
    }
}

main.cpp

#include "function_pool.h"
#include <string>
#include <iostream>
#include <mutex>
#include <functional>
#include <thread>
#include <vector>

Function_pool func_pool;

class quit_worker_exception : public std::exception {};

void example_function()
{
    std::cout << "bla" << std::endl;
}

int main()
{
    std::cout << "stating operation" << std::endl;
    int num_threads = std::thread::hardware_concurrency();
    std::cout << "number of threads = " << num_threads << std::endl;
    std::vector<std::thread> thread_pool;
    for (int i = 0; i < num_threads; i++)
    {
        thread_pool.push_back(std::thread(&Function_pool::infinite_loop_func, &func_pool));
    }

    //here we should send our functions
    for (int i = 0; i < 50; i++)
    {
        func_pool.push(example_function);
    }
    func_pool.done();
    for (unsigned int i = 0; i < thread_pool.size(); i++)
    {
        thread_pool.at(i).join();
    }
}

2
ধন্যবাদ! এটি সত্যই আমাকে সমান্তরাল থ্রেডিং ক্রিয়াকলাপ শুরু করতে সহায়তা করেছিল। আমি আপনার প্রয়োগের কিছুটা পরিবর্তিত সংস্করণ ব্যবহার করে শেষ করেছি।
রবি ক্যাপস

3

এর মতো কিছু সাহায্য করতে পারে (একটি ওয়ার্কিং অ্যাপ্লিকেশন থেকে নেওয়া)।

#include <memory>
#include <boost/asio.hpp>
#include <boost/thread.hpp>

struct thread_pool {
  typedef std::unique_ptr<boost::asio::io_service::work> asio_worker;

  thread_pool(int threads) :service(), service_worker(new asio_worker::element_type(service)) {
    for (int i = 0; i < threads; ++i) {
      auto worker = [this] { return service.run(); };
      grp.add_thread(new boost::thread(worker));
    }
  }

  template<class F>
  void enqueue(F f) {
    service.post(f);
  }

  ~thread_pool() {
    service_worker.reset();
    grp.join_all();
    service.stop();
  }

private:
  boost::asio::io_service service;
  asio_worker service_worker;
  boost::thread_group grp;
};

আপনি এটি এর মতো ব্যবহার করতে পারেন:

thread_pool pool(2);

pool.enqueue([] {
  std::cout << "Hello from Task 1\n";
});

pool.enqueue([] {
  std::cout << "Hello from Task 2\n";
});

মনে রাখবেন যে একটি দক্ষ অ্যাসিনক্রোনাস কুইং মেকানিজম পুনরায় উদ্ভাবন করা তুচ্ছ নয়।

বুস্ট :: অ্যাসিও :: আইও_সার্ভিস একটি অত্যন্ত দক্ষ বাস্তবায়ন, বা আসলে প্ল্যাটফর্ম-নির্দিষ্ট মোড়কের সংগ্রহ (যেমন এটি উইন্ডোজে I / O সমাপ্তি পোর্টগুলি মোড়ানো) wra


2
সি ++ 11 এর সাথে কি এটাই বাড়াতে হবে? বলবে না, std::threadযথেষ্ট?
einpoklum

সেখানে কোন সমতূল্য stdজন্য boost::thread_group। উদাহরণস্বরূপ boost::thread_groupএকটি সংগ্রহ boost::thread। তবে অবশ্যই, এর boost::thread_groupএকটি vectorএর সাথে প্রতিস্থাপন করা খুব সহজ std::thread
rustyx

3

সম্পাদনা করুন: এটির জন্য এখন সি ++ 17 এবং ধারণাগুলি প্রয়োজন। (9/12/16 পর্যন্ত কেবলমাত্র জি ++ 6.0+ই যথেষ্ট)

এটির কারণে টেমপ্লেট কেটে নেওয়া অনেক বেশি নির্ভুল, যদিও এটি একটি নতুন সংকলক পাওয়ার প্রচেষ্টা সার্থক worth আমি এখনও এমন কোনও ফাংশন পাইনি যার জন্য স্পষ্টত টেম্পলেট যুক্তিগুলির প্রয়োজন requires

এটি এখন যে কোনও উপযুক্ত কলযোগ্য বস্তু গ্রহণ করে ( এবং এটি এখনও স্ট্যাটিকালি টাইপসেইফ !!! )।

এটিতে এখন একই এপিআই ব্যবহার করে একটি alচ্ছিক সবুজ থ্রেডিং অগ্রাধিকার থ্রেড পুল অন্তর্ভুক্ত রয়েছে। যদিও এই শ্রেণিটি কেবল পসিক্স। এটি ucontext_tইউজারস্পেস টাস্ক স্যুইচিংয়ের জন্য এপিআই ব্যবহার করে ।


আমি এটির জন্য একটি সাধারণ গ্রন্থাগার তৈরি করেছি। ব্যবহারের উদাহরণ নীচে দেওয়া হল। (আমি এটির উত্তর দিচ্ছি কারণ এটি সিদ্ধান্ত নেওয়ার আগে আমার নিজের এটি একটি জিনিস খুঁজে পেয়েছিল এটি নিজেই লিখতে হবে write)

bool is_prime(int n){
  // Determine if n is prime.
}

int main(){
  thread_pool pool(8); // 8 threads

  list<future<bool>> results;
  for(int n = 2;n < 10000;n++){
    // Submit a job to the pool.
    results.emplace_back(pool.async(is_prime, n));
  }

  int n = 2;
  for(auto i = results.begin();i != results.end();i++, n++){
    // i is an iterator pointing to a future representing the result of is_prime(n)
    cout << n << " ";
    bool prime = i->get(); // Wait for the task is_prime(n) to finish and get the result.
    if(prime)
      cout << "is prime";
    else
      cout << "is not prime";
    cout << endl;
  }  
}

আপনি যে asyncকোনও ফাংশনকে কোনও (বা বাতিল) রিটার্ন মান এবং যে কোনও (বা না) যুক্তি দিয়ে পাস করতে পারেন এবং এটি একটি সম্পর্কিত ফিরিয়ে দেবে std::future। ফলাফল পেতে (বা কোনও কাজ শেষ না হওয়া পর্যন্ত অপেক্ষা করুন) আপনি get()ভবিষ্যতের দিকে কল করুন।

এখানে গিথুব রয়েছে: https://github.com/Tyler-Hardin/thread_pool


1
আশ্চর্যজনক মনে হচ্ছে, তবে ভিট-ভিটের শিরোনামের সাথে তুলনা করা দুর্দান্ত হবে!
জোনাথন এইচ

1
@ Sh3ljohn, এটিকে এক নজরে দেখে মনে হচ্ছে এপিআইতে তারা মূলত একই। ভিট-ভিট বুস্টের লকফ্রি ক্যু ব্যবহার করে যা আমার চেয়ে ভাল। (তবে আমার লক্ষ্যটি ছিল বিশেষত কেবলমাত্র এসটিডি দিয়েই করা। * আমি মনে করি আমি লকফ্রি সারিতে নিজেরাই প্রয়োগ করতে পারতাম, তবে এটি কঠোর এবং ত্রুটিযুক্ত বলে মনে হচ্ছে।) এছাড়াও, ভিট-ভিটের কোনও সম্পর্কিত .cpp নেই, যা এমন লোকদের জন্য ব্যবহার করা সহজ যাঁরা জানেন না যে তারা কী করছেন। (যেমন github.com/Tyler-Hardin/thread_pool/issues/1 )
টাইলার

তার / তারও একটি স্ট্যালি-একমাত্র সমাধান রয়েছে যা আমি গত কয়েক ঘন্টা ধরে কাঁটাচ্ছি, প্রথমে এটি জায়গা থেকে সমস্ত ভাগ করে নেওয়া পয়েন্টার সহ আপনার চেয়ে আরও জটিল দেখায়, তবে এটি হট-রাইজিং সঠিকভাবে পরিচালনা করার জন্য প্রয়োজন।
জোনাথন এইচ

@ শ থ্যালজাহান, আহ, আমি গরম আকার পরিবর্তন করিনি। ওটা সুন্দর. আমি এটি সম্পর্কে উদ্বিগ্ন না হওয়ার কারণ বেছে নিয়েছি কারণ এটি প্রকৃত ব্যবহারের ক্ষেত্রে নয়। (আমি ব্যক্তিগতভাবে আকার পরিবর্তন করতে চাই, এমন কোনও ক্ষেত্রে আমি ভাবতে পারি না তবে এটি কল্পনার অভাবে হতে পারে))
টাইলার

1
উদাহরণস্বরূপ ব্যবহারের ক্ষেত্রে: আপনি কোনও সার্ভারে একটি RESTful এপিআই চালাচ্ছেন এবং পরিষেবাটি সম্পূর্ণরূপে বন্ধ করার প্রয়োজন ছাড়াই অস্থায়ীভাবে রক্ষণাবেক্ষণের উদ্দেশ্যে রিসোর্স বরাদ্দ হ্রাস করতে হবে।
জোনাথন এইচ

3

এটি আরেকটি থ্রেড পুল বাস্তবায়ন যা খুব সাধারণ, সহজেই বোঝা যায় এবং ব্যবহারযোগ্য, কেবল সি ++ 11 স্ট্যান্ডার্ড লাইব্রেরি ব্যবহার করে এবং আপনার ব্যবহারগুলির জন্য এটি দেখতে বা পরিবর্তন করা যেতে পারে, যদি আপনি থ্রেড ব্যবহার করতে চান তবে একটি দুর্দান্ত স্টার্টার হওয়া উচিত পুল:

https://github.com/progschj/ThreadPool


3

আপনি বুস্ট লাইব্রেরি থেকে থ্রেডপুল ব্যবহার করতে পারেন :

void my_task(){...}

int main(){
    int threadNumbers = thread::hardware_concurrency();
    boost::asio::thread_pool pool(threadNumbers);

    // Submit a function to the pool.
    boost::asio::post(pool, my_task);

    // Submit a lambda object to the pool.
    boost::asio::post(pool, []() {
      ...
    });
}

আপনি ওপেন সোর্স সম্প্রদায় থেকে থ্রেডপুল ব্যবহার করতে পারেন :

void first_task() {...}    
void second_task() {...}

int main(){
    int threadNumbers = thread::hardware_concurrency();
    pool tp(threadNumbers);

    // Add some tasks to the pool.
    tp.schedule(&first_task);
    tp.schedule(&second_task);
}

1

এসটিএলের বাইরে কোনও নির্ভরতা ছাড়াই একটি থ্রেডপুল সম্পূর্ণভাবে সম্ভব। ঠিক একই সমস্যাটির সমাধান করতে আমি সম্প্রতি একটি ছোট্ট হেডার-থ্রেডপুল লাইব্রেরি লিখেছি । এটি গতিশীল পুলের আকার পরিবর্তন (রানটাইমের সময় কর্মীদের সংখ্যা পরিবর্তন করা), প্রতীক্ষা, থামানো, বিরতি, পুনরায় শুরু এবং আরও অনেক কিছু সমর্থন করে। আশা করি এটি আপনার কাজে লাগবে।


দেখে মনে হচ্ছে আপনি নিজের গিথব অ্যাকাউন্ট মুছে ফেলেছেন (বা লিঙ্কটি ভুল পেয়েছে)। আপনি কি এই কোডটি অন্য কোথাও সরিয়ে নিয়েছেন?
rtpax

1
@ আরটিপ্যাক্স আমি রেপো সরিয়ে নিয়েছি - আমি তার প্রতিফলন করার জন্য উত্তর আপডেট করেছি।
ক্যান্টর্ডস্ট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.