Я пытался подсчитать длительность цикла for с помощью 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
но когда я увеличиваю границу счетчика цикла до очень очень большого значения, это внезапно принимает навсегда !! если я поставлю с<100000000 это занимает 0 наносек, но если я добавлю один ‘0’ справа, это займет вечность !!
ответ :
как сказал WhiZTiM, компилятор удаляет цикл, потому что он не делает ничего полезного (спасибо gcc <3), но мы действительно не хотим, чтобы это происходило, когда мы тестируем алгоритмы, чтобы увидеть, какой из них быстрее на разных компиляторах (а не этот особенный), чтобы сделать это, мы можем вставить строку asm в цикл. asm("")
, пустой асм, в любом месте цикла. Это скажет компилятору, что есть некоторые низкоуровневые операции, которые он не может оптимизировать! или мы можем использовать ключевое слово volitile для любой переменной, используемой в цикле, которая не позволяет компилятору выполнять какую-либо оптимизацию, связанную с этой переменной. спасибо всем, я надеюсь, что это помогает
Прежде всего, использование инициализированных переменных как в.
Оптимизатор определенно выяснил, что цикл бесполезен (действительно, какими должны быть значения 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;;
}
Видеть это Жить на Колиру
Других решений пока нет …