1

我试图使用 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(""),一个空的汇编,在循环中的任何地方。这将告诉编译器有一些他无法优化的低级操作!,或者我们可以对循环中使用的任何变量使用 volitile 关键字,以防止编译器执行与该变量相关的任何优化。谢谢大家,我希望这会有所帮助

4

1 回答 1

0

首先,使用初始化变量是一种罪过。

优化器肯定发现循环是无用的(真的,循环中的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;;
}

在Coliru现场观看

于 2016-10-02T22:22:50.740 回答