【问题标题】:boost::threads based queue algorithmboost::threads 基于队列算法
【发布时间】:2012-05-09 18:14:00
【问题描述】:

假设有一个 std::deque 指向要执行的任务的指针队列,那么确保一次运行的线程数限制为 CPU 内核数的最佳方法是什么?即,任务完成后,其余任务随后启动。

我为之前的帖子制作了以下代码,我现在遇到的问题是我不确定实施我所描述的最佳策略,并且认为这可能值得征求意见。

请注意,我上面提到的“std::deque queue of pointers”并不是指代码中的 deque mtasks。我不希望从这个双端队列中弹出任务,因为我正在使用它来存储以前完成的任务。

在程序类型中,类似 task p1 p2 p3 p4 p5 ,在提示符下,然后 info 检查每个的当前状态。请注意,目前所有 5 项任务大约在同一时间完成。但是,我真正想要的是前 2 个完成(双核机器),然后是接下来的 2 个等。

这样做的原因是,在实践中这些任务可能需要几个小时,因此我想尽快获得第一批结果,以便我可以将它们加载到 MATLAB 或其他任何东西中。

我希望我清楚自己和示例代码。我猜 thread::hardware_concurrency() 涵盖了核心部分的数量......

谢谢 A.

#include <iostream>  
#include <string>
#include <sstream>
#include <boost/thread.hpp>  

using namespace std;

class task {
public:
    string mname;
    bool completed;
    void start()
    {
        int a = 0;
        for (int i=0 ; i<10000; i++)
        {
            for (int j=0 ; j<100000; j++)
            {
                a= i*2;
            }
        }
        this->completed = true;
    }
    task(string name)
    {
        mname = name;
        completed = false; 
    }
};

class taskManager{
    public:
        boost::thread_group threads;
        void startTask( string name )
        {
            //add new task to vector list           
            mtasks.push_back( task(name) );
            // execute start() on a new thread
            threads.create_thread( boost::bind( &task::start, &mtasks.back()) );
        }
        int tasksTotal()
        {
            return mtasks.size();
        }
        string taskInfo(int i)
        {
            string compstr("Not Completed");
            if ( mtasks.at(i).completed == true )
            {
                compstr = "Completed";
            }
            return mtasks.at(i).mname + " " + compstr; 
        }
    private:
        deque<task> mtasks; 
};

int main(int argc, char* argv[])  
{
    string cmd, temp;
    stringstream os;
    bool quit = false;
    taskManager mm;

    cout << "PROMPT>";

    while (quit == false)
    {
        //Wait for a valid command from user
        getline(cin,cmd);

        // Reset stringstream and assign new cmd string
        os.clear(); 
        os << "";
        os << cmd;
        //parse input string
        while (os >> temp) 
        {               
            if ( temp.compare("task") == 0 )
            {
                while (os >> temp) { mm.startTask( temp ); }                     
            }
            if ( temp.compare("info") == 0 )
            { 
                // Returns a list of all completed and not completed tasks
                for (int i = 0; i<mm.tasksTotal(); i++)
                {
                    cout << mm.taskInfo(i).c_str() << endl;
                }                           
            }
            if ( temp.compare("quit") == 0 ){ quit = true; }
        }

        cout << "PROMPT>";
    }

    mm.threads.join_all();      

    return 0;  
};

【问题讨论】:

  • 按定义,一次运行的线程数已经受限于CPU核数,但我猜你的意思是应该没有准备好的线程而不是不能得到一个核:)跨度>
  • @MartinJames 是的,据我了解,可以启动比内核更多的线程,并且操作系统会为每个线程提供运行时间。就我而言(我认为 - 如果我错了,请纠正我)我需要将运行的线程数限制为内核数,以便充分利用可用内核,同时最大限度地减少单个任务结果的完成时间.
  • 我不确定我是否理解。如果你想让前两个任务在双核机器上快速完成,你能不能不只是在一个线程池中创建两个线程,在一个队列上等待?另一个线程安全的出队和信号量,或其他样式的阻塞集合有什么问题?
  • @MartinJames 线程安全的出队是我想过的事情,但我不确定如何限制一次运行的线程数,因此发布了。现在是线程池模式,这正是我需要实现的,但我不知道这个术语。
  • @MartinJames 一分钱刚刚掉——我应该只在第一个实例中创建 2 个线程,只要它不为空,它们就应该从线程安全的双端队列中弹出另一个任务并处理它。 :)

标签: c++ multithreading boost-thread deque


【解决方案1】:

您所描述的是线程池模式,其中您有固定数量的线程和一组要使用这些线程执行的任务(#tasks > #threads)。

线程池模式上的wikipedia 条目有更多信息。你可以自己写,也可以使用非官方的boost threadpool library

【讨论】:

  • 线程池模式看起来很完美,我不知道术语,我很高兴我把帖子放了。 +1
猜你喜欢
  • 2011-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 2015-10-07
相关资源
最近更新 更多