C++ 静态变量与堆栈动态变量的访问效率

C++ 静态变量与堆栈动态变量的访问效率,c++,static,C++,Static,有一个任务,我应该创建两个子程序,每个子程序有三个大数组(至少100x100)。一个是静态的,另一个是堆栈动态的,“子程序中的代码必须对静态矩阵执行大量矩阵乘法运算,并对过程计时。”同样,它也必须对堆栈动态执行同样的操作 根据我的理解,使用静态数组应该比使用堆栈动态数组快得多,但我看到了不同的结果 #include <ctime> #include <cstdlib> #include <iostream> using namespace std; void

有一个任务,我应该创建两个子程序,每个子程序有三个大数组(至少100x100)。一个是静态的,另一个是堆栈动态的,“子程序中的代码必须对静态矩阵执行大量矩阵乘法运算,并对过程计时。”同样,它也必须对堆栈动态执行同样的操作

根据我的理解,使用静态数组应该比使用堆栈动态数组快得多,但我看到了不同的结果

#include <ctime>
#include <cstdlib>
#include <iostream>
using namespace std;

void staticMatrix();
void stackDynamicMatrix();

int main() {
    staticMatrix();
    stackDynamicMatrix();
    return 0;
}

void staticMatrix(){
    static int a[100][100];
    static int b[100][100];
    static int c[100][100];

    // Fill with random numbers
    for (int i = 0; i < 100; i++)
        for (int j = 0; j < 100; j++) {
            a[i][j] = rand() % 100 + 1;
            b[i][j] = rand() % 100 + 1;
        }
    time_t begin;
    time(&begin);
    // Do large number of matrix multiplications
    for (double k = 0; k < 300000; k++)
        for (int i = 0; i < 100; i++)
            for (int j = 0; j < 100; j++) {
                c[i][j] = a[i][j] * b[i][j];
            }
    time_t end;
    time(&end);

    cout<<"Time elapsed for Static: " << difftime(end, begin)<<endl;

    return;
}

void stackDynamicMatrix(){
    int d[100][100];
    int e[100][100];
    int f[100][100];

    // Fill with random numbers
    for (int i = 0; i < 100; i++)
        for (int j = 0; j < 100; j++) {
            d[i][j] = rand() % 100 + 1;
            e[i][j] = rand() % 100 + 1;
        }
    time_t begin2;
    time(&begin2);
    // Do large number of matrix multiplications
    for (double k = 0; k < 300000; k++)
        for (int i = 0; i < 100; i++)
            for (int j = 0; j < 100; j++) {
                f[i][j] = d[i][j] * e[i][j];
            }
    time_t end2;
    time(&end2);
    cout<<"Time elapsed for Stack-Dynamic: " << difftime(end2, begin2)<<endl;

    return;
}
#包括
#包括
#包括
使用名称空间std;
空矩阵();
void stackDynamicMatrix();
int main(){
静态矩阵();
stackDynamicMatrix();
返回0;
}
void矩阵(){
静态int a[100][100];
静态int b[100][100];
静态int c[100][100];
//用随机数填充
对于(int i=0;i<100;i++)
对于(int j=0;j<100;j++){
a[i][j]=rand()%100+1;
b[i][j]=rand()%100+1;
}
时间还没有开始;
时间(&开始);
//做大量的矩阵乘法
对于(双k=0;k<300000;k++)
对于(int i=0;i<100;i++)
对于(int j=0;j<100;j++){
c[i][j]=a[i][j]*b[i][j];
}
时间不会结束;
时间(&结束);

cout在运行基准测试时,您会遇到一些常见错误:

  • 不准确的计时器
  • 发布优化过多
  • 只运行一个测试
在调试/发布版本中运行MSVC 2010中未经修改的代码(更精确的计时器除外)会让我:

  • 调试静态=7900毫秒
  • 调试堆栈动态=9500毫秒
  • 释放静态=1900毫秒
  • 释放堆栈动态=420毫秒
首先,您需要使用精度更高的计时器来获得更有意义的结果。在Windows快速基准测试中,我通常使用
GetTickCount()
,但更准确的计时器是
QueryPerformanceCounter()
。或者如果您有兼容的编译器,则使用C++11标准
std::chrono::high_resolution\u clock

从调试/发布时间可以看出,优化器足够聪明,可以将大多数堆栈动态情况简化为零。它“知道”您从不使用for循环的结果,并且可以消除所有或大部分for循环

为了获得有意义的基准测试,您必须“欺骗”编译器,使其不优化此类循环

void stackDynamicMatrix() {
    size_t Sum = 0;
    ...

    for (double k = 0; k < 300000; k++)
        for (int i = 0; i < 100; i++)
            for (int j = 0; j < 100; j++) {
                c[i][j] = a[i][j] * b[i][j];
                Sum += c[i][j];             //Added
            }

    ...
    cout < <"Sum = " << Sum << endl;   //Be sure to output result
}

并且忽略每个测试中的第一个基准测试。有时缓存会弄乱第一个基准测试结果(除非这是您试图度量的).

为什么使用静态数组要比使用堆栈上的数组快?我看不出有什么好的理由可以期待显著的差异。@JerryCoffin:我看到了他看到的差异的一个很好的理由——静态结果矩阵的生存期没有结束,自动结果矩阵的生存期是结束,因此编译器可以优化将后者以及所有提供它的循环完全化。@BenVoigt:对不起,我可能应该说得更清楚。我指的是在实际代码中的实际使用(或在一个费劲才产生有意义结果的基准测试中)。一般来说(做完全相同的工作)自动数组可能有一个很小的优势。堆栈中的页面很可能已经在缓存中,并且当数组和控制数据相邻放置时,它们之间缓存冲突的可能性较小。几乎可以肯定,任何差异都太小而不必担心。@JerryCoffin这取决于体系结构。在Sparc上,与访问静态变量相比,访问局部变量通常需要更少的一条指令。在没有有效的基于地址的计算机上(如旧的8080),访问局部变量的速度可能要慢得多。我怀疑大多数现代体系结构都针对现代编程技术进行了优化,访问局部变量的速度至少与访问静态变量的速度一样快(如果不是更快的话)。
int main() {
    staticMatrix(); //Ignore this result
    staticMatrix();
    staticMatrix();
    staticMatrix();
    stackDynamicMatrix(); //Ignore this result
    stackDynamicMatrix();
    stackDynamicMatrix();
    stackDynamicMatrix();
    return 0;
}