多个嵌套for循环与单个for循环

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.我也在发布模式下编译.然而,尽管这两种方法在时间上更相似,但第二种方法仍然稍微快一些.

是的,这是所有的测试代码(减去时序/输出函数,但这些并不是特定于问题).

Arn*_*rno 9

当testX变量在代码中的某个地方使用时,编译器不会"优化"循环.当我只在代码中添加一行输出testX时,结果如下:

  • single for loop: 1.218 ms
  • nested 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 ms
  • nested 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 ms
  • nested for loop: 1.216 ms

结果:

  • 嵌套循环是不是比单圈速度.