C++ 使用std::chrono::staddy_clock对线程/异步中的代码进行基准测试

C++ 使用std::chrono::staddy_clock对线程/异步中的代码进行基准测试,c++,multithreading,std,future,chrono,C++,Multithreading,Std,Future,Chrono,假设我要在多个线程中运行大量计算(以及基准CPU时间)。例如: #include <chrono> #include <future> #include <iostream> #include <vector> using unit_t = std::chrono::nanoseconds; unit_t::rep expensive_computation() { auto start = std::chrono::steady_c

假设我要在多个线程中运行大量计算(以及基准CPU时间)。例如:

#include <chrono>
#include <future>
#include <iostream>
#include <vector>


using unit_t = std::chrono::nanoseconds;

unit_t::rep expensive_computation() {
    auto start = std::chrono::steady_clock::now();
    // Something time-consuming here...
    auto end = std::chrono::steady_clock::now();

    auto duration = std::chrono::duration_cast<unit_t>(end - start).count();

    return duration;
}

int main() {
    std::vector<std::future<unit_t::rep>> computations;

    for (int i = 0; i < 100; i++) {
        computations.push_back(std::async(expensive_computation));
    }

    for (size_t i = 0; i < computations.size(); i++) {
        auto duration = computations[i].get();
        std::cout << "#" << i << " took " << duration << "ns" << std::endl;
    }
}
#包括
#包括
#包括
#包括
使用单位t=std::chrono::纳秒;
unit_t::rep昂贵的_计算(){
自动启动=标准::时钟::稳定时钟::现在();
//这里有些费时的事情。。。
自动结束=标准::时钟::稳定时钟::现在();
自动持续时间=std::chrono::持续时间_cast(结束-开始).count();
返回时间;
}
int main(){
向量计算;
对于(int i=0;i<100;i++){
push_back(std::async(昂贵的_计算));
}
对于(size_t i=0;istd::cout该标准规定了
稳定时钟
模型物理时间(与CPU时间相反)

从[时间.时钟.稳定]:

稳定\u时钟
的对象表示时间点的值不会随着物理时间的推移而减少的时钟,
时间点的值
相对于实时以稳定的速率前进。也就是说,时钟可能不会被调整

也就是说,实现对物理时间建模的好坏是一个QOI问题

如果您的实验结果不令人满意,
的客户还可以编写自己的自定义时钟,这些时钟在
库中具有一流的地位

这意味着,如果线程处于睡眠状态,则稳定的时钟将 仍然是滴答作响,这一次将被错误地包括在 该线程的持续时间

但是,正如标准所规定的那样,这不会是错误的 类
std::chrono::staid_clock
它测量物理时间,而不是CPU时间或任何其他时间。请参见以下内容:

稳定时钟
的对象表示值为
时间点
绝不会随着物理时间的推移而减少,并且
时间点
的值相对于 实时


也就是说,您的代码看起来很好,因为它将为您提供每个线程运行所测量的时间。您有理由在这里测量CPU时间吗?如果有,请在注释中告诉我。

感谢标准链接。我会仔细阅读!物理时间也许可以(在我的特定情况下,计算不需要I/O)。我在这里的真正目标是,生成的计时应该等同于所有计算都是连续运行和计时的。只要是这样,那就好了。@BaileyParker是的,就是这样。很高兴我能提供帮助。@BaileyParker从你对另一个答案的评论来看,我可能没有完全理解你对accu的要求这里很有意思。你在文章中的代码在数学上并不等同于连续运行相同的任务。只是在测量执行所有任务的总时间方面相当。我认为你应该在100%空闲的机器上进行测量。在这种情况下,使用哪个时钟并不重要(如果您在加载的计算机上测量事物,您的基准可能不准确,即使您测量线程时间:超线程、缓存使用率等可能会影响结果)。未来就绪检查应该在将来之前改进代码。get()。在ns分辨率(也是CPU域)下,检查系统的最低分辨率可能是必要的。@geza这是一个非常好的观点。我目前正在努力保护这样的环境。即使在100%空闲的机器上,我也会担心一些计算会比其他计算花费更长的时间(这些可能会受到负载的更大影响,可能会人为地增加它们的时间)。但我怀疑这在很大程度上是不可避免的。@seccpur你所说的“未来就绪检查”是什么意思?
future.get()
不调用
future.wait()
?在玩具示例中,我并不特别关心结果的延迟(仅仅是整个运行时)。此外,ns分辨率是一个玩具示例的产物。我真正的基准分辨率可能是μs或ms。@BaileyParker:“即使在100%空闲的机器上,我也会担心的一个问题是,某些计算比其他计算花费的时间要长得多”。你这是什么意思?(请注意:请记住关闭CPU频率缩放)。哎呀,似乎我当时误解了这里的意思。我将用实际计算来尝试一下,看看这是否令人满意(不过,确定是否存在干扰可能会很棘手).在研究过程中,我确实遇到了一个可能更精确的自定义时钟包装?正如@geza在评论中所指出的那样,我的目标是在缓存、超线程等条件下实现与串行执行相同的时间。感谢您的洞察力!