Multithreading notify_one()的性能真的这么差吗?

Multithreading notify_one()的性能真的这么差吗?,multithreading,c++11,concurrency,condition-variable,Multithreading,C++11,Concurrency,Condition Variable,对于下面的度量,我一直在使用x86_64 GNU/Linux,内核4.4.0-109-generic#132 Ubuntu SMP运行在AMD FX(tm)-8150八核处理器上(具有64字节缓存线大小) 完整的源代码可以在这里获得: 它独立于其他库。只需使用以下工具进行编译: g++ -pthread -std=c++11 -O3 condition_variable_test.cxx 我在这里真正尝试的是测量当一个或多个线程实际在等待时执行对notify_one()的调用所需的时间,相对于

对于下面的度量,我一直在使用x86_64 GNU/Linux,内核4.4.0-109-generic#132 Ubuntu SMP运行在AMD FX(tm)-8150八核处理器上(具有64字节缓存线大小)

完整的源代码可以在这里获得:

它独立于其他库。只需使用以下工具进行编译:

g++ -pthread -std=c++11 -O3 condition_variable_test.cxx
我在这里真正尝试的是测量当一个或多个线程实际在等待时执行对
notify_one()
的调用所需的时间,相对于没有线程在使用的条件变量上等待所需的时间

令我惊讶的是,我发现这两种情况都在微秒范围内:当一个线程等待时,大约需要14到20微秒;当没有线程等待时,所需的时间明显减少,但仍然至少为1微秒

换句话说,如果您有一个生产者/消费者场景,每次对消费者无事可做时,您让他们调用
wait()
,每次生产者向队列写入新内容时,您调用
notify_one()
假设std::condition_变量的实现足够智能,不会在没有线程等待的情况下花费大量时间。。然后,哦,可怕的是,您的应用程序将比我编写的代码慢得多,我编写的代码是为了测试线程等待时调用
notify_one()
需要多长时间

似乎我使用的代码是加速这些场景所必须的。这让我很困惑:为什么我写的代码不是std::condition\u变量的一部分

所讨论的代码是,而不是:

// Producer thread:
add_something_to_queue();
cv.notify_one();

// Consumer thread:
if (queue.empty())
{
  std::unique_lock<std::mutex> lk(m);
  cv.wait(lk);
}
直接=1时:

All started!
Thread 4 statistics: avg: 1.2e+03ns, min: 4.9e+02ns, max: 1.4e+03ns, stddev: 2.5e+02ns
The average time spend on calling notify_one() (0 calls) was: 1156.49 ns.
Thread 4 finished.
Thread 5 finished.
Thread 8 finished.
Thread 7 finished.
Thread 6 finished.
Thread 3 statistics: avg: 1.2e+03ns, min: 5.9e+02ns, max: 1.5e+03ns, stddev: 2.4e+02ns
The average time spend on calling notify_one() (0 calls) was: 1164.52 ns.
Thread 3 finished.
Thread 2 statistics: avg: 1.2e+03ns, min: 1.6e+02ns, max: 1.4e+03ns, stddev: 2.9e+02ns
The average time spend on calling notify_one() (0 calls) was: 1166.93 ns.
Thread 2 finished.
Thread 1 statistics: avg: 1.2e+03ns, min: 95ns, max: 1.4e+03ns, stddev: 3.2e+02ns
The average time spend on calling notify_one() (0 calls) was: 1167.81 ns.
Thread 1 finished.
All finished!

后一个输出中的“0个调用”实际上大约是20000000个调用。

首先,在调用
notify\u one()
之前,不需要锁定互斥锁。这是一种悲观的看法:被唤醒的线程会立即再次被阻塞,等待通知程序释放互斥体。在这种情况下,您确实需要该锁,否则对notify_one()的调用可能会丢失:消费者线程可能会增加s_idle,因此,在进入wait()之前,生产者线程可以调用notify_one()不会做任何事情,因为没有任何线程在等待。然后增加s_idle的线程将进入wait()。我想要的是,s_idle真正反映了正在等待的线程的确切数量(可能会被唤醒)。这就是互斥锁的作用。请注意,如果我不使用互斥锁,则计时不会改变,这不会导致延迟。您好,您有没有找到问题的答案?我还注意到,条件变量似乎比我的应用程序中预期的要慢。@thc没有,这里没有答案-我自己也没有进一步研究它。
All started!
Thread 1 statistics: avg: 1.9ns, min: 1.8ns, max: 2ns, stddev: 0.039ns
The average time spend on calling notify_one() (726141 calls) was: 17995.5 - 21070.1 ns.
Thread 1 finished.
Thread Thread Thread 5 finished.
8 finished.
7 finished.
Thread 6 finished.
Thread 3 statistics: avg: 1.9ns, min: 1.7ns, max: 2.1ns, stddev: 0.088ns
The average time spend on calling notify_one() (726143 calls) was: 17207.3 - 22278.5 ns.
Thread 3 finished.
Thread 2 statistics: avg: 1.9ns, min: 1.8ns, max: 2ns, stddev: 0.055ns
The average time spend on calling notify_one() (726143 calls) was: 17910.1 - 21626.5 ns.
Thread 2 finished.
Thread 4 statistics: avg: 1.9ns, min: 1.6ns, max: 2ns, stddev: 0.092ns
The average time spend on calling notify_one() (726143 calls) was: 17337.5 - 22567.8 ns.
Thread 4 finished.
All finished!
All started!
Thread 4 statistics: avg: 1.2e+03ns, min: 4.9e+02ns, max: 1.4e+03ns, stddev: 2.5e+02ns
The average time spend on calling notify_one() (0 calls) was: 1156.49 ns.
Thread 4 finished.
Thread 5 finished.
Thread 8 finished.
Thread 7 finished.
Thread 6 finished.
Thread 3 statistics: avg: 1.2e+03ns, min: 5.9e+02ns, max: 1.5e+03ns, stddev: 2.4e+02ns
The average time spend on calling notify_one() (0 calls) was: 1164.52 ns.
Thread 3 finished.
Thread 2 statistics: avg: 1.2e+03ns, min: 1.6e+02ns, max: 1.4e+03ns, stddev: 2.9e+02ns
The average time spend on calling notify_one() (0 calls) was: 1166.93 ns.
Thread 2 finished.
Thread 1 statistics: avg: 1.2e+03ns, min: 95ns, max: 1.4e+03ns, stddev: 3.2e+02ns
The average time spend on calling notify_one() (0 calls) was: 1167.81 ns.
Thread 1 finished.
All finished!