堆栈分配功能(性能)

MrP*_*rik 8 c c++ performance stack allocation

在我的小型性能问题调查期间,我注意到一个有趣的堆栈分配功能,这里是测量时间的模板:

#include <chrono>
#include <iostream>

using namespace std;
using namespace std::chrono;

int x; //for simple optimization suppression
void foo();

int main()
{   
    const size_t n = 10000000; //ten millions
    auto start = high_resolution_clock::now();

    for (size_t i = 0; i < n; i++)
    {
        foo();
    }

    auto finish = high_resolution_clock::now();
    cout << duration_cast<milliseconds>(finish - start).count() << endl;
}
Run Code Online (Sandbox Code Playgroud)

现在全部是关于foo()实现,在每个实现中将总共分配500000 ints:

  1. 分配在一个块中:

    void foo()
    {
        const int size = 500000;
        int a1[size];
    
        x = a1[size - 1];
    }  
    
    Run Code Online (Sandbox Code Playgroud)

    结果:7.3秒 ;

  2. 分为两个部分:

    void foo()
    {
        const int size = 250000;
        int a1[size];
        int a2[size];
    
        x = a1[size - 1] + a2[size - 1];
    }
    
    Run Code Online (Sandbox Code Playgroud)

    结果:3.5秒 ;

  3. 分为四个部分:

    void foo()
    {
        const int size = 125000;
        int a1[size];
        int a2[size];
        int a3[size];
        int a4[size];
    
        x = a1[size - 1] + a2[size - 1] +
            a3[size - 1] + a4[size - 1];
    } 
    
    Run Code Online (Sandbox Code Playgroud)

    结果:1.8秒.

等等......我将它分成16个块,结果时间为0.38秒.


请向我解释一下,为什么以及如何发生这种情况?
我使用了MSVC 2013(v120),发布版本.

UPD:
我的机器是x64平台.我用Win32平台编译它.
当我用x64平台编译它时,它在所有情况下产生大约40ms.
为什么平台选择如此影响?

120*_*arm 8

从VS2015 Update 3的反汇编看,在2和4数组版本中foo,编译器优化了未使用的数组,以便它只为每个函数中的1个数组保留堆栈空间.由于后面的函数具有较小的数组,因此花费的时间更少 对x的赋值为两个/所有4个数组读取相同的内存位置.(由于数组未初始化,因此从它们读取是未定义的行为.)如果不优化代码,则会有2或4个不同的数组从中读取.

这些函数花费的时间很长,这是由于__chkstk执行的堆栈探测作为堆栈溢出检测的一部分(当编译器需要超过1页的空间来保存所有局部变量时,这是必需的).