c++11中线程的性能

Performance of threads in c++11

本文关键字:性能 线程 c++11      更新时间:2023-10-16

我对最新的基于pthreads和Ubuntu开发环境的gcc中互斥锁和消息传递的性能很感兴趣。一个很好的一般性问题是吃饭的哲学家,每个哲学家都使用左手和右手的邻居共用的左右手叉。我将哲学家的数量增加到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个是等的。所以我的没有锁的简单算法不仅更快,而且在不同线程之间有更好的处理分配。

谁能想出一个更好的方法来解决这个问题?我担心,当我实现一个具有多个线程的复杂系统时,如果我遵循传统的互斥锁和消息传递技术,我将以比必要的更慢的速度结束,并且可能导致系统中各个线程的处理不平衡。

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

表示具体的点:

我担心,当我实现一个具有多个线程的复杂系统时,如果我遵循传统的互斥锁和消息传递技术,我将以比必要的更慢的速度结束,并且可能导致系统中各个线程的处理不平衡。

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

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

总的来说,这涉及到一个工程问题,它将具体到你想要解决的问题,操作系统和硬件。