コードを見返しているとき、std::this_thread::yield()
猛的引入眼帘,C11
里面的语法糖,用了不少,__INLINE_CODE_2__里面的语法糖,用了不少,__を初めて見ました。今まで気づいていませんでした。
マニュアルを確認する前に、最初に考えたのは非同期処理との関連性だった。__INLINE_CODE_0__Boostライブラリのコルーチン実装でこの単語が使われているが、ここではコルーチンとは関係ないだろう。制御ロジックは通常のスレッドに関連している。
文書
yield
この関数の正確性は、実装に依存し、特に使用されているOSスケジューラ機構とシステムの状態に左右されます。例えば、先着順リアルタイムスケジューラ(LinuxのSCHED_FIFO)は、現在のスレッドを中断し、同じ優先度の他のスレッドがなければ、準備完了キューの末尾に配置します(他のスレッドが存在しない場合、yieldの効果はありません)。
sleep_for
指定されたsleep_durationの間、現在のスレッドの実行をブロックします。 この関数は、スケジューリングやリソース競合により、sleep_durationよりも長くブロックされる可能性がある。 標準ライブラリでは、安定したクロックで時間を計測することを推奨します。システム時間を用いる実装の場合、待ち時間もクロック調整に影響される可能性があります。
分析
二つの関数は、現在のスレッドがスレッドを占有しなくなるようにするもので、効果はプラットフォームによって異なるようですね。ここまでの説明だけではまだよくわからないので、コードを実行して動作を確認してみます。
シンクパッド ノートPC(Visual Studio Community Edition 2022)、テンセントクラウド S2 スタンダードサーバー(gcc8.5)
実行プラットフォーム | 関数 | 初回/μs | 第2回/μs | 第3回/μs |
---|---|---|---|---|
Windows | sleep_for | 9872 | 1884 | 11302 |
Windows | yield | 119 | 100 | 100 |
Linux | sleep_for | 171 | 168 | 167 |
Linux | yield | 101 | 102 | 101 |
動作結果から容易に理解できるように、オペレーティングシステムの実現方法の違いにより、高精度スリープでは、INLINE_CODE_0__BOLD_2yield
の方が適しています。
時間精度が__INLINE_CODE_0__に向上しても、両者の差はそれほど顕著ではない。
#include <iostream>
#include <chrono>
#include <thread>
// 建议其他线程运行一小段时间的“忙睡眠”
void little_sleep(std::chrono::microseconds us)
{
auto start = std::chrono::high_resolution_clock::now();
auto end = start + us;
do {
std::this_thread::yield();
} while (std::chrono::high_resolution_clock::now() < end);
}
int main()
{
auto start = std::chrono::high_resolution_clock::now();
little_sleep(std::chrono::microseconds(100));
std::this_thread::sleep_for(std::chrono::microseconds(100));
auto elapsed = std::chrono::high_resolution_clock::now() - start;
std::cout << "waited for "
<< std::chrono::duration_cast<std::chrono::microseconds>(elapsed).count()
<< " microseconds\n";
}