Tech Notes

conditional_variableのnotify~waitにかかる時間

リアルタイムな用途で使ってみようと思ったら意外と使えなさそうなことが分かったので、今回このようなプログラムを書いて調べてみた。

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <chrono>
#include <thread>
#include <condition_variable>
using namespace std;

using INT = long long;
using UINT = unsigned long long;

vector<INT> rec;

void func()
{
	bool flag = false;
	mutex mt;
	condition_variable cv;

	chrono::high_resolution_clock::time_point t1, t2;

	thread th([&]()
		{
			{
				lock_guard<mutex> glk(mt);

				int w = rand() % 100 + 10;

				this_thread::sleep_for(chrono::microseconds(w));

				flag = true;
			}
			t1 = chrono::high_resolution_clock::now();
			cv.notify_one();
		});

	{
		unique_lock<mutex> ulk(mt);
		cv.wait(ulk, [&]() {return flag; });
		t2 = chrono::high_resolution_clock::now();
		flag = false;

		auto t = (t2 - t1).count();

		cout << "time: " << t << endl;
		rec.push_back(t);
	}

	th.join();
}

int main()
{
	for (size_t i = 0; i < 1000; i++)
	{
		func();
	}

	cout << "ave: " << double(accumulate(rec.begin(), rec.end(), 0)) / rec.size() << endl;

	sort(rec.begin(), rec.end());

	cout << "med: " << rec[rec.size() / 2] << endl;
	cout << "max: " << rec[rec.size() - 1] << endl;
	cout << "min: " << rec[0] << endl;

	return 0;
}

実行の結果(個別タイムは略)

ave: 37224.5
med: 22879
max: 5809471
min: 6802

単位はナノ秒。平均37usはまだ良いとして、最悪の場合6ms近くもかかっている。これではちょっと本当に速度が求められる場合は厳しいという気がする。

マイコンのタイマー割り込みみたいな使い方ができはしないかと言う邪な考えが脳内を席巻していたのだが無理そうという結論だった。もちろん十分に遅い用途では何の問題もないとは思うが。