c ++中线程的性能11

时间:2013-06-09 14:09:23

标签: c++ c++11 concurrency

我对使用基于pthreads和Ubuntu开发环境的线程的最新gcc中的互斥和消息传递的性能感兴趣。一个很好的通用问题是餐饮哲学家,每个哲学家都使用lh和rh fork与左手和右手邻居共享。我将哲学家的数量增加到99,以保持我的四核处理器忙碌。

    int result = try_lock(forks[lhf], forks[rhf]);

上面的代码允许我的哲学家尝试抓住他们需要吃的两把叉子。

    // if the forks are locked then start eating
    if (result == -1)
    {
        state[j] = philosophers::State::Eating;
        eating[j]++;
        if (longestWait < waiting[j])
        {
            longestWait = waiting[j];
        }
        waiting[j] = 0;
    } else {
        state[j] = philosophers::State::Thinking;
        thinking[j]++;
        waiting[j]++;
    }
上面的代码监视着我的哲学家们进食或思考进步,这取决于他们是否设法保留这两个分叉。

    {
        testEnd te(eating[j]+thinking[j]-1);
        unique_lock<mutex> lk(cycleDone);
        endCycle.wait(lk, te);
    }

上述代码等待所有哲学家完成选择后哲学家可以自由地进行新的尝试:

    if ( philosophers::State::Eating == state[j] )
    {
        state[j] = philosophers::State::Thinking;
        forks[lhf].unlock();
        forks[rhf].unlock();
    }

我有一个监视哲学家的主线程,并将他们从一个周期移动到下一个周期,让他们大约10秒吃饭并尽可能多地思考。 结果是大约9540个周期,一些哲学家挨饿,其他人有足够的食物和大量的思考时间!因此,我需要保护我的哲学家免受饥饿和等待太久,所以我增加了更多的逻辑,以防止过度饮食,要求饮食哲学家释放和思考,而不是在经过一小段休息之后抓住同样的叉子:

    // protect the philosopher against starvation
    if (State::Thinking == previous)
    {
        result = try_lock(forks[lhf], forks[rhf]);
    }

现在我有9598个周期,每个哲学家都有相对平等的饮食份额(2620 - 2681)并且考虑最长的等待时间14。不错。但是我并不满足所以现在我摆脱了所有的互斥锁和锁定,并且让偶数哲学家在偶数周期中吃东西并且奇怪的哲学家在奇怪的周期中吃东西时保持简单。我使用一种简单的方法来同化哲学家

while (counter < counters[j])
{
    this_thread::yield();
}

防止哲学家使用全球循环计数器进食或思考太多次。同一时期,哲学家管理大约73543个周期,吃36400个,等待不超过3个周期。因此,我没有锁定的简单算法更快,并且在各种线程之间有更好的处理分配。

有人能想出更好的方法来解决这个问题吗?我担心当我实现一个具有多个线程的复杂系统时,如果我遵循传统的互斥和消息传递技术,我将最终在系统中的各个线程上进行比必要和可能的不平衡处理更慢的速度。

1 个答案:

答案 0 :(得分:2)

这是一种探索c ++中线程问题的有趣方法。

解决具体问题:

  

我担心当我实现一个具有多个线程的复杂系统时,如果我遵循传统的互斥和消息传递技术,我将最终在系统中的各个线程上进行慢于必要和可能的不平衡处理。

不幸的是,我能给你的最好答案是,这是一个有根据的恐惧。调度和同步的成本非常特定于应用程序 - 这在设计大型系统时成为工程决策。首先,调度是NP-Hard(http://en.wikipedia.org/wiki/Multiprocessor_scheduling),但具有良好的近似值。

就您的具体示例而言,我认为很难根据您提供的结果得出一般性结论 - 有一个主要的关键点:粗粒度同步和细粒度同步之间的权衡。这是一个研究得很好的问题,一些研究可能会有所帮助(例如http://ieeexplore.ieee.org/xpls/abs_all.jsp?arnumber=744377&tag=1)。

总的来说,这涉及到一个工程问题,该问题将针对您要解决的问题,操作系统和硬件。