在实现一个简单的信号量时,我试图计算在忙等待循环中花费的平均时间,并以纳秒为单位休眠这段时间。无论哪种方式,睡眠1纳秒似乎都可以达到同样的效果:当我打电话时,速度会快速增加(大约快6倍)...
std::this_thread::sleep_for(std::chrono::nanoseconds(1));
...在信号量的P()
函数的忙等待循环中。
我相信睡眠会大大减少争用,但我希望有更多知识渊博的人给我一个更确定的答案。
使用std::this_thread::yield();
比简单的自动锁定更有利于执行时间,但仍然具有较高的CPU使用率(90-100%)。睡眠方法使其保持在10-15%;线程仍然是交错的,因此并不是一个线程连续执行其所有指令。
我尽可能地将此示例最小化以突出显示代码的相关部分。我在问题的最后提供了一个完整实现的演示链接。
#include <atomic>
struct semaphore
{
public:
explicit semaphore( int const max_concurrency );
void P()
{
// why does this sleep improve performance so much?
while ( !try_decrease_count() )
std::this_thread::sleep_for( std::chrono::nanoseconds( 1 ) );
}
void V()
{
count_.fetch_add( 1 );
}
private:
bool try_decrease_count();
std::atomic<int> count_;
};
semaphore::semaphore( int const max_count )
: count_{ max_count }
{}
bool semaphore::try_decrease_count()
{
int old_count{ count_.load() };
do
{
if ( !old_count ) return false;
} while ( !count_.compare_exchange_strong( old_count, old_count - 1 ) );
return true;
}
这些包括完整的代码和测试。
使用sleep_for进行演示:http://coliru.stacked-crooked.com/a/ff16411d9a884556
没有sleep_for的演示:http://coliru.stacked-crooked.com/a/2df776f0a03425b1