【发布时间】:2014-02-24 09:31:10
【问题描述】:
以下代码从一个解释为浮点数的零数组复制到另一个数组,并打印此操作的时间。正如我所看到的许多无操作循环只是被编译器(包括 gcc)优化掉的情况,我一直在等待在更改我的复制数组程序的某个时候它会停止复制。
#include <iostream>
#include <cstring>
#include <sys/time.h>
static inline long double currentTime()
{
timespec ts;
clock_gettime(CLOCK_MONOTONIC,&ts);
return ts.tv_sec+(long double)(ts.tv_nsec)*1e-9;
}
int main()
{
size_t W=20000,H=10000;
float* data1=new float[W*H];
float* data2=new float[W*H];
memset(data1,0,W*H*sizeof(float));
memset(data2,0,W*H*sizeof(float));
long double time1=currentTime();
for(int q=0;q<16;++q) // take more time
for(int k=0;k<W*H;++k)
data2[k]=data1[k];
long double time2=currentTime();
std::cout << (time2-time1)*1e+3 << " ms\n";
delete[] data1;
delete[] data2;
}
我用 g++ 4.8.1 命令g++ main.cpp -o test -std=c++0x -O3 -lrt 编译了这个。这个程序为我打印6952.17 ms。 (我必须设置 ulimit -s 2000000 以使其不会崩溃。)
我还尝试将使用 new 的数组创建更改为自动 VLA,删除 memsets,但这不会改变 g++ 的行为(除了多次更改时间)。
似乎编译器可以证明这段代码不会做任何明智的事情,那么为什么不优化循环呢?
【问题讨论】:
-
从我们的角度来看这不是操作,但是编译器不知道也无法知道 data1 和 data2 的内存块的内容已经相等。
-
我不能给出明确的答案,但是 a) 任何优化都不是强制性的。 b) 你有两个
new,但没有delete。 -
@deviantfan 我依赖于退出时释放的内存,尽管标准似乎无法保证。
-
即使主要操作系统可以做到这一点,省略删除也是完全错误的。而且,据我所知,这甚至可以解决您的优化问题(“可以”,而不是“将”)。
-
@pan-:它确实知道,但是不使用 data2 计算的结果。我同意 OP,这种代码通常在我的实践中被优化掉,我必须采取特殊措施确保在编写此类基准时不会发生这种情况。
标签: c++ gcc optimization