有一个任务,我应该创建两个子程序,每个子程序有三个大数组(至少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秒(听起来不对)。
如果有人能够解释我在这里做错了什么或误会,那将不胜感激。
答案 0 :(得分:1)
运行基准测试时遇到一些常见错误:
在MSVC 2010的调试/发布版本中运行代码未经修改(除了更准确的计时器)让我:
首先,您需要使用更精确的计时器来获得更有意义的结果。在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...
添加到所有基准测试中,无论他们是否需要。
通过添加总和,我在发布版本中得到以下结果:
每次都在基准时间的自然变化范围内。虽然它不会影响这个特定的基准,但我也会这样做:
int main() {
staticMatrix(); //Ignore this result
staticMatrix();
staticMatrix();
staticMatrix();
stackDynamicMatrix(); //Ignore this result
stackDynamicMatrix();
stackDynamicMatrix();
stackDynamicMatrix();
return 0;
}
并忽略每个测试中的第一个基准。有时缓存可能会破坏第一个基准测试结果(除非您正在尝试测量)。