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实现似乎提供了不可预测的结果

  • 有没有办法睡上几微秒
  • 对于实现微秒睡眠的STL线程,是否有一个好的跨平台替代方案

  • 简短回答:
    std::chrono::sleep\u for
    是跨平台解决方案,但其精度由实现定义。没有多少操作系统实现您想要的精度。无论如何,当然不是Windows。您可能想使用
    std::chrono::high_resolution_clock
    进行基准测试。@LHLaurini
    high_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