我创建了一个大型布尔二维数组(5000X5000,总共 250 亿个元素,大小为 23MB)。然后我循环遍历并用随机的 true 或 false 实例化每个元素。然后我循环并读取每个元素。所有 2500 万个元素的读取时间约为 100 毫秒。
23MB 太大,无法放入 CPU 缓存,而且我认为我的程序太简单,无法从任何类型的编译器优化中受益,所以我得出的结论是否正确,即该程序在大约 100 毫秒内从 RAM 读取 2500 万个元素?
#include "stdafx.h"
#include <iostream>
#include <chrono>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
bool **locs;
locs = new bool*[5000];
for(int i = 0; i < 5000; i++)
locs[i] = new bool[5000];
for(int i = 0; i < 5000; i++)
for(int i2 = 0; i2 < 5000; i2++)
locs[i][i2] = rand() % 2 == 0 ? true : false;
int *idx = new int [5000*5000];
for(int i = 0; i < 5000*5000; i++)
*(idx + i) = rand() % 4999;
bool val;
int memAccesses = 0;
auto start = std::chrono::high_resolution_clock::now();
for(int i = 0; i < 5000*5000; i++) {
val = locs[*(idx + i)][*(idx + ++i)];
memAccesses += 2;
}
auto finish = std::chrono::high_resolution_clock::now();
std::cout << std::chrono::duration_cast<std::chrono::nanoseconds>(finish-start).count() << " ns\n";
std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(finish-start).count() << " ms\n";
cout << "TOTAL MEMORY ACCESSES: " << memAccesses << endl;
cout << "The size of the array in memory is " << ((sizeof(bool)*5000*5000)/1048576) << "MB";
int exit; cin >> exit;
return 0;
}
/*
OUTPUT IS:
137013700 ns
137 ms
TOTAL MEMORY ACCESSES: 25000000
The size of the array in memory is 23MB
*/
Run Code Online (Sandbox Code Playgroud)
正如其他答案所提到的,您看到的“速度”(即使 CPU 正在执行您的代码并且它没有被编译器剥离)约为 250 MBps,这对于现代系统来说是非常非常低的数字。
然而,你的方法对我来说似乎有缺陷(诚然,我不是基准测试专家。)以下是我看到的问题:
您对内存访问的计数不正确。根据编译器生成的具体代码,此行:
val = locs[*(idx + i)][*(idx + ++i)];
Run Code Online (Sandbox Code Playgroud)
实际上可能会访问内存系统 4 到 9 次。
i、idx、locs和val都在寄存器中或者消除了对它们的访问,那么您需要 read *(idx + i)、 read locs[*(idx + i)](记住这locs是指向数组的指针数组,而不是二维数组) read *(idx + ++i),最后是 read locs[*(idx + i)][*(idx + ++i)]。其中一些可能会被缓存,但这不太可能,因为缓存抖动正在发生。++i(读取,然后写回),一次访问idx,一次访问locs,一次访问val。我不知道,您甚至可能需要对单个读取进行另一次读取i和/或对两次idx出现进行两次读取(由于指针别名等原因)。总而言之,我认为您不能从您的程序中得出很多有用的信息。抱歉,记忆是非常复杂的!