2016-10-02 4 views
0

Я пытался подсчитать продолжительность, занимаемую циклом for, используя std :: chrono, но он дает 0 наносекунд, даже если я сделаю цикл более длинным, увеличив связанное значение, это код:подсчет продолжительности с std :: chrono дает 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 

но когда я increament границы счетчика цикла очень очень огромное значение он вдруг принимает навсегда !! , если я положил c < 100000000, он принимает 0 наносекук, но если я добавлю «0» справа, это займет навсегда !!

ответ: как сказал WhiZTiM, компилятор удаляет петлю, потому что он не делает ничего полезного (спасибо Gcc < 3), но мы действительно не хотим, чтобы это произошло, когда мы проводим тестирование алгоритмов, чтобы увидеть причем один из них работает быстрее на разных компиляторах (а не на этом spesific), чтобы сделать это, мы можем вставить строку asm в цикл. asm(""), пустой asm, в любом месте цикла. Это скажет компилятору, что есть некоторые операции низкого уровня, которые он не может оптимизировать! , или мы можем использовать ключевое слово volitile для любой переменной, используемой в цикле, которая не позволяет компилятору выполнять какую-либо оптимизацию, связанную с этой переменной. спасибо всем, я надеюсь, что это помогает

+0

х, у и г не инициализированы. Неопределенное поведение. –

+0

Я добавил их позже, теперь они инициализированы, но проблема сохраняется! –

ответ

0

Прежде всего, используя инициализированные переменные в a sin.

Оптимизатор определенно понял, цикл бесполезно (на самом деле, каковы должны быть значения 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;; 
} 

BTW, ключевое слово register устарело.


Для НКИ и лязга, есть способ, чтобы «попугать» оптимизатор от оптимизации отказа от использования определенных переменных. Я использую эту функцию:

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

+0

Да, я тоже так думал :), потрясающий gcc - это огромный XD, позже я добавил переменные x, y, z, они не являются причиной, теперь они инициализированы, но это ничего не меняет, так что вы можете дать пример цикла, который нельзя игнорировать? –

+0

@DhiaHassen, Да, пожалуйста, см. Мой обновленный ответ. – WhiZTiM

+0

спасибо, и мы можем использовать также 'volatile int c;' для счетчика циклов, который мешает компилятору делать какую-либо оптимизацию, связанную с ним. –