使用std::chrono计算持续时间,当它应该花费很长时间时,结果是0纳秒

counting duration with std::chrono gives 0 nanosecond when it should take long

本文关键字:长时间 结果是 纳秒 计算 chrono std 持续时间 使用      更新时间:2023-10-16

我试图使用std::chrono计算for循环的持续时间,但它给出了0纳秒,即使我通过增加绑定值使循环花费更长时间,这是代码:

#pragma pack(1) // dont align let's let it take longer
struct Foo{
    int x;
    char c;
    int z;
} ;
void take_time()
{
    Foo f;
    auto t1 = std::chrono::system_clock::now();
    register int c = 0;
    int x=0,y=0,z=1;
    for (c=0;c<10000;c++){ // even if i put  1000000000 it will take 0 nanosec !!!!!
        f.z = x+y;
        f.z += z-x+y;
    }
   std::cout<<"ntoken time : "<< std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now()-t1).count()<<std::endl;;
}
输出:

token time : 0

但是当我将循环计数器的边界增加到非常非常大的值时,它突然需要永远!!如果我输入c<100000000,它需要0纳秒,但如果我在右边加一个"0",它需要永远!!

答案:正如WhiZTiM所说,编译器正在删除循环,因为它没有做任何有用的事情(感谢gcc <3),但我们真的不希望这种情况发生,当我们在测试算法时,看看哪一个在不同的编译器上更快(而不是这个特定的编译器),为此,我们可以插入asm行到循环中。asm(""),一个空asm,在循环中的任何地方。这将告诉编译器,有一些低级操作是他无法优化的!或者,我们可以对循环中使用的任何变量使用volatile关键字,以防止编译器对该变量进行任何优化。谢谢大家,希望对大家有所帮助

首先,使用初始化的变量是错误的。

Optimizer明确指出循环是无用的(真的,循环中x, y, z的值应该是什么);循环的结果没有被使用(没有副作用),所以它在生成的代码中删除了循环。

void take_time()
{
    Foo f;
    auto t1 = std::chrono::system_clock::now();
    register int c = 0;
    int x,y,z;
    ///// Result not used
    for (c=0;c<10000;c++){ // even if i put  1000000000 it will take 0 nanosec !!!!!
        f.z = x+y;
        f.z += z-x+y;
    }
    /// We can discard the above
   std::cout<<"ntoken time : "<< std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now()-t1).count()<<std::endl;;
}

顺便说一句,此处的register关键字已弃用。


对于GCC和clang,有一种方法可以"吓唬"优化器不去优化某些变量的使用。我使用这个函数:

template<typename T>
void scareTheOptimizer(T& x){
    asm volatile("" :: "p"((volatile void*)&x) : "memory");
}

所以,当你在循环中调用它时,你现在应该看到一些计时。

void take_time()
{
    Foo f;
    auto t1 = std::chrono::system_clock::now();
    int c = 0;
    int x=0,y=0,z=1;
    for (c=0;c<10000;c++){
        f.z = x+y;
        scareTheOptimizer(f.z);             /// <---- Added Here
        f.z += z-x+y;
    }
   std::cout<<"ntoken time : "<< std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now()-t1).count()<<std::endl;;
}

看Live On Coliru