C++ 如何让线程睡眠几微秒?(MinGW中的睡眠_的实现无效)
由于C++ 如何让线程睡眠几微秒?(MinGW中的睡眠_的实现无效),c++,multithreading,c++11,cross-platform,sleep,C++,Multithreading,C++11,Cross Platform,Sleep,由于std::chrono::sleep\u for接受微秒,我希望它能够以合理的偏差睡眠微秒(睡眠时间稍微长一点,绝对不能短一点) 然而,事实证明我错了,这似乎不可能与STL。 的sleep\u的MSVC实现使线程睡眠几毫秒(!!!)。 MinGW实现直接忽略了命令的sleep_(微秒,1毫秒),并且已经注意到多次错误唤醒(尽管标准中没有规定此类行为) 当MinGW被告知睡眠1毫秒时,它的睡眠时间不合理地超过1毫秒或MSVC 下面是我用于测试的代码片段 #include <thread&
std::chrono::sleep\u for
接受微秒,我希望它能够以合理的偏差睡眠微秒(睡眠时间稍微长一点,绝对不能短一点)
然而,事实证明我错了,这似乎不可能与STL。
的sleep\u的MSVC实现使线程睡眠几毫秒(!!!)。
MinGW实现直接忽略了
命令的
sleep_(微秒,1毫秒),并且已经注意到多次错误唤醒(尽管标准中没有规定此类行为)
当MinGW被告知睡眠1毫秒时,它的睡眠时间不合理地超过1毫秒或MSVC
下面是我用于测试的代码片段
#include <thread>
#include <condition_variable>
#include <chrono>
#include <iostream>
#include <locale>
struct separate_thousands : std::numpunct<char>
{
char_type do_thousands_sep() const override { return ','; } // separate with commas
string_type do_grouping() const override { return "\3"; } // groups of 3 digit
};
class StopWatch
{
std::chrono::steady_clock::time_point start_;
public:
StopWatch()
: start_(std::chrono::steady_clock::now())
{}
void Reset()
{
start_ = std::chrono::steady_clock::now();
}
std::chrono::nanoseconds Result() const
{
return std::chrono::steady_clock::now() - start_;
}
template <typename MetricPrefix>
std::chrono::duration<long long, MetricPrefix> Result(MetricPrefix) const
{
return std::chrono::duration_cast<
std::chrono::duration<long long, MetricPrefix>
>(Result());
}
template <typename MetricPrefix>
operator std::chrono::duration<long long, MetricPrefix>() const
{
return Result(MetricPrefix());
}
};
template <typename DurationType>
std::chrono::nanoseconds SleepFor(DurationType duration)
{
StopWatch sw{};
std::this_thread::sleep_for(duration);
return sw;
}
template <typename DurationType>
std::chrono::nanoseconds WaitFor(DurationType duration)
{
std::mutex cvMutex{};
std::condition_variable cv{};
StopWatch sw{};
std::unique_lock<std::mutex> ul{cvMutex};
cv.wait_for(ul, std::chrono::microseconds(1));
return sw;
}
int main()
{
std::cout.imbue(std::locale(std::cin.getloc(), new separate_thousands()));
StopWatch sw{};
std::chrono::nanoseconds durationNanosec = sw;
std::cout << "Duration between 2 \"std::chrono::steady_clock::now()\" calls: " <<
durationNanosec.count() << " nanoseconds" << std::endl;
std::cout << "Duration of sleep_for 1 microsecond "
<< SleepFor(std::chrono::microseconds(1)).count()
<< " nanoseconds" << std::endl;
std::cout << "Duration of sleep_for 5 microseconds "
<< SleepFor(std::chrono::microseconds(5)).count()
<< " nanoseconds" << std::endl;
std::cout << "Duration of sleep_for 100 microseconds "
<< SleepFor(std::chrono::microseconds(100)).count()
<< " nanoseconds" << std::endl;
std::cout << "Duration of sleep_for 500 microseconds "
<< SleepFor(std::chrono::microseconds(500)).count()
<< " nanoseconds" << std::endl;
std::cout << "Duration of sleep_for 1 milliseconds "
<< SleepFor(std::chrono::milliseconds(1)).count()
<< " nanoseconds" << std::endl;
// this executes far longer than 1 second on MinGW!
for (size_t i = 0; i != 1000; ++i)
{
std::chrono::nanoseconds duration = SleepFor(std::chrono::milliseconds(1));
if (duration < std::chrono::milliseconds(1))
{
std::cout << "Slept less than 1ms : " << duration.count() << " nanoseconds" << std::endl;
break;
}
}
// this executes far longer than 2 seconds on MinGW!
for (size_t i = 0; i != 1000; ++i)
{
std::chrono::nanoseconds duration = SleepFor(std::chrono::milliseconds(2));
if (duration < std::chrono::milliseconds(2))
{
std::cout << "Slept less than 2ms : " << duration.count() << " nanoseconds" << std::endl;
break;
}
}
std::cout << "Duration of sleep_for 10 milliseconds "
<< SleepFor(std::chrono::milliseconds(10)).count()
<< " nanoseconds" << std::endl;
std::cout << "Duration of condition_variable::wait_for 1 microsecond "
<< WaitFor(std::chrono::microseconds(1)).count()
<< " nanoseconds" << std::endl;
std::cout << "Duration of condition_variable::wait_for 5 microseconds "
<< WaitFor(std::chrono::microseconds(5)).count()
<< " nanoseconds" << std::endl;
std::cout << "Duration of condition_variable::wait_for 1 millisecond "
<< WaitFor(std::chrono::milliseconds(1)).count()
<< " nanoseconds" << std::endl;
std::cout << "Duration of condition_variable::wait_for 10 milliseconds "
<< WaitFor(std::chrono::milliseconds(10)).count()
<< " nanoseconds" << std::endl;
return 0;
}
使用MSVC:
Duration between 2 "std::chrono::steady_clock::now()" calls: 300 nanoseconds
Duration of sleep_for 1 microsecond 13,200 nanoseconds
Duration of sleep_for 5 microseconds 1,694,100 nanoseconds
Duration of sleep_for 100 microseconds 1,572,900 nanoseconds
Duration of sleep_for 500 microseconds 1,694,300 nanoseconds
Duration of sleep_for 1 milliseconds 1,645,000 nanoseconds
Duration of sleep_for 10 milliseconds 10,976,100 nanoseconds
Duration of condition_variable::wait_for 1 microsecond 46,100 nanoseconds
Duration of condition_variable::wait_for 5 microseconds 21,300 nanoseconds
Duration of condition_variable::wait_for 1 millisecond 28,700 nanoseconds
Duration of condition_variable::wait_for 10 milliseconds 22,500 nanoseconds
我知道我可以使用忙等待来等待纳秒,但这是不行的,因为我不想浪费CPU资源。
此外,MinGW实现似乎提供了不可预测的结果
简短回答:
std::chrono::sleep\u for
是跨平台解决方案,但其精度由实现定义。没有多少操作系统实现您想要的精度。无论如何,当然不是Windows。您可能想使用std::chrono::high_resolution_clock
进行基准测试。@LHLaurinihigh_resolution_clock
在MinGW中是系统时钟的别名,而在MSVC中则是稳定的_clock
<代码>稳定时钟
是测量时间的正确方法。@SergeyKolesnik Posix和Windows都有优先级设置,您可以使用设置。但我没有MinGW,所以我不相信它会一致。由于睡眠时间很短,繁忙的等待不一定会给系统带来更大的负载。考虑所有的上下文切换所有的<代码>睡眠>对于或<代码> SLIPEPI直到暗示。它们也需要CPU时间。顺便说一句,因为普通的Windows和Linux不是实时操作系统,所以您必须牺牲精度或CPU。
Duration between 2 "std::chrono::steady_clock::now()" calls: 300 nanoseconds
Duration of sleep_for 1 microsecond 13,200 nanoseconds
Duration of sleep_for 5 microseconds 1,694,100 nanoseconds
Duration of sleep_for 100 microseconds 1,572,900 nanoseconds
Duration of sleep_for 500 microseconds 1,694,300 nanoseconds
Duration of sleep_for 1 milliseconds 1,645,000 nanoseconds
Duration of sleep_for 10 milliseconds 10,976,100 nanoseconds
Duration of condition_variable::wait_for 1 microsecond 46,100 nanoseconds
Duration of condition_variable::wait_for 5 microseconds 21,300 nanoseconds
Duration of condition_variable::wait_for 1 millisecond 28,700 nanoseconds
Duration of condition_variable::wait_for 10 milliseconds 22,500 nanoseconds