代码之家  ›  专栏  ›  技术社区  ›  fbrereto

最大化工作线程利用率

  •  1
  • fbrereto  · 技术社区  · 14 年前

    为了解决一个问题(更好地理解多任务处理),我编写了一个小型线程池实现。这个线程池会增加一些工作线程,当线程池的客户端添加任务时,这些工作线程会将任务弹出队列。就本问题而言,当任务队列为空时,工作线程将全部终止。

    在做了一些基本的基准测试之后,我发现应用程序花费了大约60%的时间等待获取队列锁。可能这主要发生在工作线程中。

    这仅仅是我没有给工人足够的线程去做的一种暗示,还是其他什么?我是否缺少一些直接的方法来提高工作线程吞吐量?

    编辑 :这里是一些粗略的伪代码,应该可以说明一些事情。这是在工作线程执行期间获取/释放锁的仅有的两个地方(这是应用程序运行时间的绝大部分)

    std::list<task_t> task_list;
    
    // Called by the client to add tasks to the thread pool
    void insert_task(const task_t& task)
    {
        lock_type listlock(task_mutex);
    
        task_list.push_back(task);
    }
    
    // The base routine of each thread in the pool. Some details
    // such as lifetime management have been omitted for clarity.
    void worker_thread_base()
    {
        while (true)
        {
            task_t task;
    
            {
            lock_type listlock(task_mutex);
    
            if (task_list.empty())
                continue;
    
            task = task_list.front();
    
            task_list.pop_front();
            }
    
            do_task(task);
        }
    }
    
    2 回复  |  直到 14 年前
        1
  •  0
  •   Reed Copsey    14 年前

    你的设计是建立在每个线程坐和“旋转”试图获得锁。除非每个工作线程都在执行工作,否则这种情况将持续发生,在这种情况下,锁将处于未获取状态,工作将发生。

    由于所有线程都只是坐在一个锁上,在锁上旋转,您将需要相当多的CPU等待时间。考虑到您的设计,这在某种程度上是意料之中的。

    您会发现,如果工作线程较少,那么阻塞的时间百分比可能会急剧减少—而且在工作项多于线程的情况下,您将花费很少的时间等待该锁。

        2
  •  0
  •   GrayWizardx    14 年前

    你想用一把锁,多把锁吗?互斥?你在用什么?

    我会从你的描述中猜测(这纯粹是猜测)你有类似的东西:

    lock(theLock) {
     // ... do lots of work ...
    }
    

    解决这个问题的一种方法是,从使用显式锁(如上所述)切换到使用有信号的互斥锁,当您希望其中一个线程获取工作时,互斥锁会被触发。

    但是,如果没有看到您当前的实现,我不确定我是否可以超越这一点。