跳转至

测量缓存大小

实验1:测量模拟器使用的数据缓存大小

基本思路:从内存中连续读取数组中不同大小的数据,观察平均读取速度。

  • 当数组大小超过数据缓存之后,会出现 L1 DCache 的读缺失,平均读取速度会增加。

实验步骤

  1. 在模拟器框架中的 test 目录下,建立一个新的 cpp 文件,用于当作测试负载。这里以 test/sample_cache_size.cpp 为例。

  2. 编写如下的代码:

    constexpr unsigned ARRAY_SIZE = (1u << 20u);  // 1 MB
    char arr[ARRAY_SIZE];
    
    constexpr int totalTime = 32;
    constexpr int totalRound = 64;
    
    int main(int argc, char **argv) {
        auto testSize = ((unsigned) argv[0]);
        int sum = 0;
        unsigned step = testSize / totalTime;
    
        for (int i = 0; i < totalRound; i++)
            for (unsigned j = 0; j < testSize; j += step) sum += arr[j];
    
        asm volatile(".word 0x0000000b"  // exit mark
        );
    
        return sum;
    }
    
  3. 在实验框架的 cache-exp/cache_size.cpp 中,填充以下逻辑:

    #include "cache-exp.h"
    #include "processor.h"
    #include "runner.h"
    
    unsigned MeasureCacheSize(ProcessorAbstract *p) {
    
        // TODO: Measure the size of the cache in the given processor
        // The size will be ranged from 512 bytes to 4096 bytes(or 4 KB), and must be a power of 2
        // Return the accurate value
    
        unsigned testSize[5] = {512, 1024, 2048, 4096, 8192};
        unsigned testTime[5];
    
        for (int i = 0; i < 5; i++) {
            testTime[i] = execute(p, "./test/sample_cache_size", 1, testSize[i]);
        }
        for (int i = 0; i < 5; i++) {
            Logger::Warn(
                "With test cache size = %u, program simulator ran %u cycles.",
                testSize[i],
                testTime[i]);
        }
    
        int mx = -1;
        int idx = 0;
    
        for (int i = 0; i < 4; i++) {
            int delta = ((int) testTime[i + 1]) - ((int) testTime[i]);
            if (delta > mx) {
                mx = delta;
                idx = i;
            }
        }
    
        return testSize[idx];
    }
    
  4. 重新 cmake, 编译框架。设置参数运行 runner 程序。一个例子如下:

    ./runner -l 5 --cache-size 2048 --block-size 32 -a 4 --replace-type LRU --write-through
    
  5. 观察到类似的输出(后面的实验还没实现,可以直接 Ctrl+C 杀掉程序):

    [  INFO   ] Reading ELF file ./test/sample_cache_size
    [ WARNING ] Running ./test/sample_cache_size with following arguments: 
    512
    [  INFO   ] Reading ELF file ./test/sample_cache_size
    [ WARNING ] Running ./test/sample_cache_size with following arguments: 
    1024
    [  INFO   ] Reading ELF file ./test/sample_cache_size
    [ WARNING ] Running ./test/sample_cache_size with following arguments: 
    2048
    [  INFO   ] Reading ELF file ./test/sample_cache_size
    [ WARNING ] Running ./test/sample_cache_size with following arguments: 
    4096
    [  INFO   ] Reading ELF file ./test/sample_cache_size
    [ WARNING ] Running ./test/sample_cache_size with following arguments: 
    8192
    [ WARNING ] With test cache size = 512, program simulator ran 21052 cycles.
    [ WARNING ] With test cache size = 1024, program simulator ran 21167 cycles.
    [ WARNING ] With test cache size = 2048, program simulator ran 21292 cycles.
    [ WARNING ] With test cache size = 4096, program simulator ran 43497 cycles.
    [ WARNING ] With test cache size = 8192, program simulator ran 43420 cycles.
    [ WARNING ] Cache Size Test Result: 2048, Actual Cache Size: 2048
    
  6. 可以看到,我们的程序成功测量出了模拟器使用的数据缓存大小,实验成功。

实验步骤说明

  1. testTime[i] = execute(p, "./test/sample_cache_size", 1, testSize[i]);

    实验框架提供了一个用于执行自定义用户程序的接口,可以向用户程序传递若干整型参数

    观察 execute 函数的实现,可以得知函数将整型参数放置在了模拟器 807fff00 开始的连续地址空间上。

    在实际使用该函数传递参数时,请注意不要覆盖程序的栈空间,同时不要越界,以免发生运行时错误。

  2. auto testSize = ((unsigned) argv[0]);

    向程序传递的参数直接放置在 argv 指针开始的地址空间上,可以直接进行使用。

    注意参数类型只能为 unsigned 或者 int

  3. runner 程序

    runner 程序封装了对缓存大小,缓存行大小和缓存相连度的测试,同时可以接受 cache 的参数和规格。

    我们在评测时也会使用该 runner 程序对你编写的测量逻辑进行测试。

实验要求

  1. 重复上述步骤,完成对模拟器使用数据缓存的大小的测量。

  2. 在实验报告中简述测量逻辑。


最后更新: 2024年4月27日
作者:cuibst (84.78%), 融凯源 (15.22%)