静态与堆栈动态变量的访问效率
Access Efficiency of Static vs Stack-dynamic variables
有一个赋值,我应该创建两个子程序,每个子程序有三个大数组(至少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;
}
运行时,我看到staticMatrix()
需要~5秒,而stackDynamicMatrix()
需要0秒(听起来不太好)。
http://ideone.com/3WvdWy
如果有人能解释我在这里做错了什么或误解了什么,我将不胜感激。
您在运行基准测试时遇到了一些常见错误:
- 计时器不准确
- 发布优化过多
- 仅运行一个测试
在调试/发布版本中,在MSVC 2010中运行未修改的代码(除了更准确的计时器)让我:
- 调试静态=7900毫秒
- 调试堆栈动态=9500毫秒
- 释放静态=1900毫秒
- 释放堆栈动态=420毫秒
首先,你需要使用一个更精确的计时器来获得更有意义的结果。在Windows中,对于快速基准测试,我通常使用GetTickCount()
,但更准确的是QueryPerformanceCounter()
。如果您有兼容的编译器,也可以使用C++11标准std::chrono::high_resolution_clock
。
从调试/发布时间可以看出,优化器足够聪明,可以将大多数堆栈动态情况减少到零。它"知道"您永远不会使用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
}
这样编译器是被迫的(通常)保持循环。注意,有时编译器太聪明了,可以部分或全部优化掉这一点。当然,为了公平起见,您可以将Sum...
添加到所有基准测试中,无论它们是否需要。
加上总和,我在发布版本中得到了以下结果:
- 静态=2400毫秒
- 堆栈动态=2400毫秒
每个时间都在基准时间的自然变化范围内。虽然它不会对这个特定的基准产生太大影响,但我也会这样做:
int main() {
staticMatrix(); //Ignore this result
staticMatrix();
staticMatrix();
staticMatrix();
stackDynamicMatrix(); //Ignore this result
stackDynamicMatrix();
stackDynamicMatrix();
stackDynamicMatrix();
return 0;
}
并忽略每个测试中的第一个基准。有时缓存可能会破坏第一个基准测试结果(除非这是您试图测量的结果)。
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 访问者访问变体并返回不同类型时出错
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 写入位置0x0000000C时发生访问冲突
- 我们可以访问一个不存在的联盟的成员吗
- C++从另一个类访问公共静态向量的正确方法是什么
- 我的简单if-else语句是如何无法访问的代码
- 从C++dll访问C#中的一行主要参数
- 概念TS检查忽略私有访问修饰符
- 访问被拒绝后,c++中的故障保护代码
- 在c++中访问int到类对象的映射时出错
- 我想访问std::unique_ptr中的一个特定元素
- 为什么示例代码访问IUnknown中已删除的内存
- 访问文件中的单个字符效率低下?(C++)
- 静态与堆栈动态变量的访问效率
- 向量索引访问与迭代器访问的效率