纳秒级C++程序空转/节流

Nanosecond-level C++ program idling / throttling

我正在编写一个 C++ 程序,运行 是一个微控制器仿真器。 运行 模拟器的线程在这样的循环中执行此操作:

while(should_run) {
  simulator->RunSingleClockCycle();
}

在我的笔记本电脑上,它设法 运行 模拟器达到 60 MHz 左右。因为我只需要模拟器在 16MHz 时达到 运行,我可以在这个 while 循环中使用一个 busyloop 来减慢它的速度,使其在 16MHz 时达到 运行s,因为不可能休眠一个新的纳秒。

由于此线程正在 运行 运行模拟器和忙循环,它会导致我的一个内核使用率达到 100% CPU。如果有一种方法可以以某种方式限制线程,使微控制器 运行 处于 16MHz(没有忙循环),它将减少模拟器的资源使用。

是否有任何半跨平台(macos + linux)的方法可以在 C++ 中实现这种线程节流?

我想你可能正在寻找类似

的东西
std::this_thread::sleep_for(std::chrono::nanoseconds(1));

另请参阅:

https://en.cppreference.com/w/cpp/thread/sleep_for

https://en.cppreference.com/w/cpp/thread/sleep_until

https://en.cppreference.com/w/cpp/chrono/duration

在传统硬件上,您永远不会获得纳秒级计时。例如,在我的系统上 运行ning 这段代码(不考虑竞争条件):

#include <thread>
#include <chrono>
#include <future>
#include <iostream>



int main()
{
    unsigned int counter = 0;
    auto res = std::async(std::launch::async, [&]()
    {
        while (true)
        {
            std::cout << "Count : " << counter << '\n';
            counter = 0;
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    });


    auto timetoWait = 1'000'000'000 / 16'000'000;
    while (true)
    {
        ++counter;
        std::this_thread::sleep_for(std::chrono::nanoseconds(timetoWait));
    }
}

我每秒最多获得 600-700k "operations"。与模拟器应该 运行 的 1600 万相去甚远。

你最好只是忙着循环。

您可以为此目的使用 chrono,我很确定它适用于 linux 和 windows。

我不知道有什么方法可以 100% 准确地测量时间。这些 chrono 调用有时会自己计时,但它们相对准确。

#include <iostream>
#include <chrono>

bool wait(long long nanoseconds)
{
    // if the number of ns to wait is not zero
    if(0 != nanoseconds)
    {
        // init high resolution clock
        std::chrono::high_resolution_clock                              hrc             = {};
        // get the start and stop timepoints
        std::chrono::time_point<std::chrono::high_resolution_clock>     start           = hrc.now(),
                                                                        stop            = hrc.now();
        // calculate the number of ns passed by subtracting the time at the start from the time at the stop
        std::chrono::nanoseconds                                        time_passed     = stop - start;

        // while the number of ns to wait for is bigger than the number of ns passed
        while(nanoseconds > time_passed.count())
        {
            // get the new stop timepoint
            stop            = hrc.now();
            // calculate the new number of ns passed
            time_passed     = stop - start;
        }

        // the wait has ended
        return true;
    }

    // the function failed
    return false;
}

int main()
{
    printf("start\n");
    // wait for 5 seconds
    wait(5000000000);
    printf("stop\n");
    getchar();

    return 0;
}

您也可以使用 rdtsc 指令以获得更高的准确性,但我无法使示例代码正常工作,所以我还是 post 它。

这里是汇编代码(我的IDE、Visual Studio不支持x64上的内联汇编所以我不得不单独写)

.model flat, c

.code

get_curr_cycle proc
cpuid
cpuid
cpuid
rdtsc
shl edx, 32
or edx, eax
mov eax, edx
retn
get_curr_cycle endp

end

这是 C++ 代码。

#include <iostream>

extern "C" unsigned int get_curr_cycle();

bool wait(long long nanoseconds)
{
    if(0 != nanoseconds)
    {
        unsigned int    start           = get_curr_cycle(),
                        stop            = get_curr_cycle();
        unsigned int    time_passed     = (stop - start);

        while(nanoseconds > time_passed)
        {
            stop            = get_curr_cycle();
            time_passed     = (stop - start);
        }
    }

    return false;
}

int main()
{
    printf("start\n");
    // wait for 5 seconds
    wait(5000000000);
    printf("stop\n");
    getchar();

    return 0;
}