【发布时间】:2021-06-24 17:54:16
【问题描述】:
好吧,我真的不知道为什么会这样。我目前正在实现一个线程容器,它以分离的方式运行无限循环,每次迭代之间限制为一定的速度。
标题:
class timeloop
{
public:
std::thread thread = { };
bool state = true;
void (*function_pointer)() = nullptr;
double ratio = 1.0f;
std::chrono::nanoseconds elapsed = { };
timeloop(
void (*function_pointer)() = nullptr
);
void function();
};
定义:
void timeloop::start()
{
this->thread = std::thread(
&loop::function,
this
);
}
void timeloop::function()
{
std::chrono::steady_clock::time_point next;
std::chrono::steady_clock::time_point start;
std::chrono::steady_clock::time_point end;
while (
this->state
)
{
start = std::chrono::high_resolution_clock::now();
next = start + std::chrono::nanoseconds(
(long long) (this->ratio * (double) std::chrono::nanoseconds::period::den)
);
if (
this->function_pointer != nullptr
)
{
this->function_pointer();
}
/***************************
this is the culprit
***************************/
std::this_thread::sleep_until(
next
);
end = std::chrono::high_resolution_clock::now();
this->elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(
end - start
);
}
}
调用代码:
timeloop* thread_draw = new timeloop(
&some_void_function
);
thread_draw->ratio = 1.0 / 128.0;
thread_draw->start();
thread_draw->thread.detach();
定义代码的行为很奇怪,特别是std::this_thread::sleep_until。对于this->ratio = 1.0 / 128.0,我预计帧速率约为128,start 和next 的计算值强化了这一点,但它莫名其妙地徘徊在60 左右。是的,我尝试将next 除以2,但是这实际上使它下降到 40 左右。
验证正常睡眠时间的额外代码:
auto diff = std::chrono::nanoseconds(
next - start
).count() / (double) std::chrono::nanoseconds::period::den;
auto equal = diff == this->ratio;
其中 equal 的计算结果为 true。
帧率计算:
double time = (double) thread_draw->elapsed.count() / (double) std::chrono::nanoseconds::period::den;
double fps = 1.0 / time;
虽然我也使用外部 FPS 计数器来验证(NVIDIA ShadowPlay 和 RivaTuner/MSI Afterburner),但它们在计算值的大约 +-5 范围内。
而且我知道它是std::this_thread::sleep_until,因为一旦我将其注释掉,帧速率就会跃升至 2000 左右。是的...
我真的对此感到困惑,尤其是看到我找不到任何其他人曾经遇到过这个问题的证据。是的,我知道睡眠功能并不完全准确,而且肯定会时不时地出现打嗝,但持续睡眠几乎是预定时间的两倍是荒谬的。
我是否可能错误配置了编译器选项或其他什么?这绝对不是性能问题,而且我有理由确定这也不是逻辑错误(查看所有计算结果如何)[除非我在某处滥用 chrono]。
【问题讨论】:
-
通过将您的
next点设置为相对于now()的呼叫,每次您失去绝对时间会给您带来的任何优势。也许这会有所帮助:stackoverflow.com/questions/35468032/…