|
今天,看到某个面经,里面有提到面试官问了这个问题,怎么写一个程序估量cpu cache的大小。看到这里,最好的做法是打开你的C++ IDE,开冲!码量估计就二三十行,需要很好的计算机基础才能写出最好的一版。
我一听,想法立马就定下来了,先申请一个足够大的buffer,然后不断重复顺序访问这个buffer的元素,然后测量平均下来的每次访问的时间。思想类似于,我用代码不断不断地重复访问某个范围让缓存尽可能地存入我想要的数据。代码如下:
#include <iostream>
#include <chrono>
#include <random>
using namespace std;
// 缓冲区大小 : 10 mb
constexpr int64_t BUF_SIZE = 10 * 1024 * 1024;
// 步长 , 每次扩大10kb
constexpr int64_t STEP = 10 * 1024;
// 每次测试循环的次数
constexpr int64_t TEST_ROUND = 10000;
void accmulate_and_observe_time(char* data, const int64_t len)
{
uniform_int_distribution<> dis(0, len - 1);
auto start_time = std::chrono::high_resolution_clock::now();
for (int64_t i = 0; i < TEST_ROUND; i++)
{
for(int64_t j = 0;j<len;j++)
data[j]--;
}
auto end_time = std::chrono::high_resolution_clock::now();
auto per_element_cost = (end_time - start_time).count() / len;
std::cout << len / 1024 << &#34;kb cost time : &#34; << per_element_cost << &#34;\n\r&#34;;
}
int main() {
char* data = new char[BUF_SIZE];
for (int64_t test_size = 1000; test_size < BUF_SIZE; test_size += STEP)
{
accmulate_and_observe_time(data, test_size);
}
delete [] data;
return 0;
}上述的测试代码有很多问题,如果你能想到不止两个的话,说明你的基础真的不错。这里没有答案,自己思考来得始终好一些,也因为我对这些问题也一知半解的。
我写完后,无论我怎么调试参数也好,代码也好,或者换编译器(因为msvc经常干些我不理解的事情),结果都一样,无论什么size,它的访问时间都大差不差。很显然,要我去面试的话,我就g了。同时也感觉到自己确实好久没写比较底层的代码了,或者看很底层的东西了,该把这些东西加上日程了。
随后我开始查看大量资料,什么版本都看了一看。最后得出了这个版本:
#include <iostream>
#include <chrono>
#include <random>
using namespace std;
// 缓冲区大小 : 10 mb
constexpr int64_t BUF_SIZE = 10 * 1024 * 1024;
// 步长 , 每次扩大50kb
constexpr int64_t STEP = 50 * 1024;
constexpr int64_t TEST_ROUND = 1000;
random_device rd;//随机数生成
mt19937 gen(rd());
void accmulate_and_observe_time(char* data, const int64_t len)
{
uniform_int_distribution<> dis(0, len - 1);
auto start_time = std::chrono::high_resolution_clock::now();
int64_t cnt = 10000 * len;
for (int64_t i = 0; i < TEST_ROUND; i++)
{
for (int64_t j = 0; j < len; j++)
data[dis(gen)]--;
}
auto end_time = std::chrono::high_resolution_clock::now();
auto per_element_cost = (end_time - start_time).count() * 10000 / cnt;
std::cout << len / 1024 << &#34;kb cost time : &#34; << per_element_cost << &#34;\n\r&#34;;
}
int main() {
char* data = (char*)calloc(BUF_SIZE, sizeof(char));
for (int64_t test_size = 1000; test_size < BUF_SIZE; test_size += STEP)
{
accmulate_and_observe_time(data, test_size);
}
free(data);
return 0;
}

这个版本参数开大点确实是能从结果上反应出cpu 的 cache大小,观察程序输出,估算cpu cache 大小也挺不错,不过跑的比较慢,需要耐心。这个版本对于直接求解cpu的各级cache大小依旧还存在一个很大的可以优化的点,不妨打开你的csapp里的cache这一章,想一想这一版本可以怎么优化? |
|