纳秒级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
在传统硬件上,您永远不会获得纳秒级计时。例如,在我的系统上 运行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;
}
我正在编写一个 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
在传统硬件上,您永远不会获得纳秒级计时。例如,在我的系统上 运行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;
}