IE盒子

搜索
查看: 185|回复: 20

如何使用C++估量CPU CACHE大小?

[复制链接]

3

主题

4

帖子

9

积分

新手上路

Rank: 1

积分
9
发表于 2022-12-30 19:09:35 | 显示全部楼层 |阅读模式
今天,看到某个面经,里面有提到面试官问了这个问题,怎么写一个程序估量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 << "kb cost time : " << per_element_cost << "\n\r";
}

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 << "kb cost time : " << per_element_cost << "\n\r";
}

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这一章,想一想这一版本可以怎么优化?
回复

使用道具 举报

3

主题

7

帖子

15

积分

新手上路

Rank: 1

积分
15
发表于 2022-12-30 19:09:54 | 显示全部楼层
艹 牛逼
回复

使用道具 举报

4

主题

7

帖子

15

积分

新手上路

Rank: 1

积分
15
发表于 2022-12-30 19:10:15 | 显示全部楼层
主要就是考察知不知道cache miss是啥,以及以及成心去制造一下cache miss。你的代码我还没看,一会儿回家看看
回复

使用道具 举报

1

主题

8

帖子

12

积分

新手上路

Rank: 1

积分
12
发表于 2022-12-30 19:10:43 | 显示全部楼层
学习学习
回复

使用道具 举报

3

主题

8

帖子

17

积分

新手上路

Rank: 1

积分
17
发表于 2022-12-30 19:11:03 | 显示全部楼层
可以向cpu发送特定指令,得到cpu的各种技术参数
回复

使用道具 举报

4

主题

10

帖子

18

积分

新手上路

Rank: 1

积分
18
发表于 2022-12-30 19:11:50 | 显示全部楼层
这问题堪比cpp届八股文了
回复

使用道具 举报

2

主题

6

帖子

10

积分

新手上路

Rank: 1

积分
10
发表于 2022-12-30 19:12:00 | 显示全部楼层
第一种感觉想法没错,只是现代cpu对于这样的连续访问优化太好了[捂脸]
回复

使用道具 举报

2

主题

7

帖子

11

积分

新手上路

Rank: 1

积分
11
发表于 2022-12-30 19:12:34 | 显示全部楼层
不能说和cache关系一点儿没有 只能说是毫不相关…
回复

使用道具 举报

3

主题

8

帖子

14

积分

新手上路

Rank: 1

积分
14
发表于 2022-12-30 19:12:57 | 显示全部楼层
为什么呢?
回复

使用道具 举报

2

主题

7

帖子

13

积分

新手上路

Rank: 1

积分
13
发表于 2022-12-30 19:13:47 | 显示全部楼层
那么你这个测试的是哪一级cache呢
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表