Jam*_*yme 5 c++ for-loop nested timing
我在c ++(MSVS)中进行了一些速度测试并得到了一个奇怪的结果.我正在测试使用一个for循环和多个嵌套for循环的速度.这是代码:
double testX = 0;
// Single loop executes in roughly 0.04 seconds
for( int i = 0; i < 27000000; i++ ){
testX += 1;
}
// Nested loop executes in roughly 0.03 seconds
for( int x = 0; x < 300; x++ ){
for( int y = 0; y < 300; y++ ){
for( int z = 0; z < 300; z++ ){
testX += 1;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,速度差异相当明显.我已经运行了很多次,这些是我看到的平均时间(这些是使用glfwGetTime()计时的).
所以我的问题是:为什么?我的测试方法不合适吗?我使用的循环太少了吗?我试过搜索谷歌,我能找到的唯一类似问题与缓存一致性的问题有关,但由于这些循环是空的,我认为它不会真正产生影响.
任何帮助都是appriciated :)
编辑:感谢评论,我意识到使用空for循环可能不是最好的测试方法...所以我已经更新了我的代码来做一些(非常)简单的操作到double.我也在发布模式下编译.然而,尽管这两种方法在时间上更相似,但第二种方法仍然稍微快一些.
是的,这是所有的测试代码(减去时序/输出函数,但这些并不是特定于问题).
当testX变量在代码中的某个地方使用时,编译器不会"优化"循环.当我只在代码中添加一行输出testX时,结果如下:
single for loop: 1.218 msnested for loop: 1.218 ms这几乎表明编译器尽可能将嵌套循环转换为单个循环.循环索引可用于防止优化:
以这种方式修改代码
for( int i = 0; i < 27000000; i++ ){
testX += i;
}
Run Code Online (Sandbox Code Playgroud)
和
for( int x = 0; x < 300; x++ ){
testX += x;
for( int y = 0; y < 300; y++ ){
testX += y;
for( int z = 0; z < 300; z++ ){
testX += z;
}
}
}
Run Code Online (Sandbox Code Playgroud)
将为嵌套循环添加一些开销但执行时间显示
single for loop: 1.224 msnested for loop: 1.226 ms这里给出的时间平均超过30.000次循环运行.
注意:testX += x;在90000中testX += x;仅贡献1,而在300中仅贡献1.因此上述两个部分仍然具有可比性.
嵌套循环并不比单循环慢得多,但你观察它们更快是不正确的.
而且:你所展示的时间大约是我观察时间的40倍.因为我在中速硬件上运行测试,所以我建议仔细检查编译器设置.也许结果是glfwGetTime()有问题的,这是你的问题的主要原因.你有没有尝试过另一种计时方案?
编辑:为了防止编译器优化,可以选择循环限制为非常量:
int lmt = rand() % 1 + 300; // random value 300 or 301
int big_lmt = lmt * lmt * lmt; // random value 27000000 or 27270901
for( int i = 0; i < big_lmt; i++ ){
testX += i;
}
for( int x = 0; x < lmt; x++ ){
testX += x;
for( int y = 0; y < lmt; y++ ){
testX += y;
for( int z = 0; z < lmt; z++ ){
testX += z;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这避免了编译器的可预测性.
结果(对于lmt = 300可比较的案例):
single for loop: 1.213 msnested for loop: 1.216 ms结果: