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

时光总嘲笑我的痴心妄想 提交于 2019-12-11 05:54:33

问题


I was trying to count the duration taken by a for loop using std::chrono but it gives 0 nanoseconds even if i make the loop take longer by increamenting the bound value , this is the code :

#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;;
}

output :

token time : 0

but when i increament the bound of the loop's counter to very very huge value it suddenly takes forever !! , if i put c<100000000 it takes 0 nanosec but if i add one '0' on the right it takes forever !!

the answer : as WhiZTiM said , the compiler is removing the loop because it does nothing useful ( thanks gcc <3 ) , but we really don't want that to happen when we are testing to algorithms to see wich one is faster on different compilers ( and not this spesific one ) , to do so we can insert an asm line into the loop . asm("") , an empty asm , anywhere in the loop . That will tell the compiler that there is some low level operations that he can't optimize ! , or we can use the volitile keyword for any variable used in the loop that prevents the compiler from doing any optimization related to that variable . thanks everyone i hope this helps


回答1:


First of all, using initialized variables is a sin.

The Optimizer definitely figured out the loop was useless(really, what should be the values of x, y, z in the loop); and result of the loop wasn't used (no side effects), so it removed the loop in the generated code.

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;;
}

BTW, the register keyword there is deprecated.


For GCC and clang, there's a way to "scare" the optimizer from optimizing out the use of certain variables. I use this function:

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

So, when you call that in your loop, you should see some timing now.

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;;
}

See it Live On Coliru



来源:https://stackoverflow.com/questions/39822307/counting-duration-with-stdchrono-gives-0-nanosecond-when-it-should-take-long

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!