用 std::chrono 计算持续时间在需要很长时间时给出 0 纳秒
counting duration with std::chrono gives 0 nanosecond when it should take long
我试图使用 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 ,在循环的任何地方。这将告诉编译器有一些他无法优化的低级操作! ,或者我们可以对循环中使用的任何变量使用 volitile 关键字,以防止编译器进行与该变量相关的任何优化。谢谢大家我希望这有帮助
首先,使用初始化变量是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;;
}
顺便说一句,register
关键字已弃用。
对于 GCC 和 clang,有一种方法可以 "scare" 优化器优化某些变量的使用。我使用这个功能:
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;;
}
我试图使用 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 ,在循环的任何地方。这将告诉编译器有一些他无法优化的低级操作! ,或者我们可以对循环中使用的任何变量使用 volitile 关键字,以防止编译器进行与该变量相关的任何优化。谢谢大家我希望这有帮助
首先,使用初始化变量是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;;
}
顺便说一句,register
关键字已弃用。
对于 GCC 和 clang,有一种方法可以 "scare" 优化器优化某些变量的使用。我使用这个功能:
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;;
}