CSAPP Cache Lab(缓存模拟器)

news2024/12/1 13:55:19

前言

在这里插入图片描述

理解高速缓存对 C 程序性能的影响,通过两部分实验达成:编写高速缓存模拟器;优化矩阵转置函数以减少高速缓存未命中次数。Part A一开始根本不知道要做什么,慢慢看官方文档,以及一些博客,和B站视频,终于知道是干嘛的了,看完别人的解题方法后,就能自己写出来了。按照我给出的一些链接,完全能搞懂Cache Simulator。Part B给大家推荐了两篇文章。

参考资料:

Lab下载链接,CacheLab官方文档,CacheLab官方课件(强烈推荐阅读),大佬笔记

新发现的宝藏网站

Part A: Writing a Cache Simulator

下面这些描述是我用豆包对官方PDF生成的总结

  • 输入输出接受 Valgrind 内存跟踪文件作为输入,模拟高速缓存的命中 / 未命中行为,输出命中、未命中和驱逐(替换)的总数。
  • 参考模拟器提供csim - ref作为参考模拟器,使用 LRU(最近最少使用)替换策略,命令行参数为Usage:./csim - ref [-hv] - s <s> - E <E> - b <b> - t <tracefile>,其中-h为帮助标志,-v为详细输出标志,-s指定组索引位数,-E指定每行关联度,-b指定块大小位数,-t指定 Valgrind 跟踪文件路径。
  • 编程规则编译无警告;为任意 S、E、b 值正确工作,需用malloc分配存储空间;忽略指令缓存访问(以 “I” 开头的行);在main函数结束时调用printSummary函数输出结果;假设内存访问已正确对齐,忽略 Valgrind 跟踪文件中的请求大小。
  • 提示先在小跟踪文件(如traces/dave.trace)上调试。参考模拟器的-v选项可显示详细的命中、未命中和驱逐信息,建议在csim.c中实现此功能辅助调试。推荐使用getopt函数解析命令行参数,需包含<getopt.h><stdlib.h><unistd.h>头文件。数据加载(L)或存储(S)操作最多导致一次缓存未命中,数据修改(M)操作视为一次加载和一次存储,可能产生两次命中、一次未命中加一次命中或一次未命中加一次命中加一次驱逐。

下面是高速缓存(S, E, B, m)的通用组织。高速缓存是一个高速缓存的数组。每个组包含一个或多个行,每个行包含一个有效位,一些标记位,以及一个数据块。高速缓存的结构将m个地址位划分成了t个标记位,s个索引位和b个块偏移位。详见CSAPP6.4强烈推荐B站视频,看完之后就知道这个实验要做什么了,理解计算机Cache(一):从块到缓存结构,以及逐步推出映射策略和理解计算机Cache(二):缓存与内存的交互。

在这里插入图片描述

下面是看完别人的解法后,又自己写的代码

#include "cachelab.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>

typedef struct cache_line 
{
    int valid_bit; // 有效位
    unsigned tag;  // 标记位
    int stamp;     // 时间戳用于LRU
}cache_line;

// S(2^s)块大小, s组索引.
// E缓存块(2^b)行数, b块偏移.
int S, s, B, b, E;
// 命中,未命中,替换
int hit, miss, eviction;
char *filepath;
cache_line **cache;

void init()
{
    // malloc cache[S][E]
    cache = (cache_line**)malloc(sizeof(cache_line*) * S);
    for (int i = 0; i < S; i++)
        cache[i] = (cache_line*)malloc(sizeof(cache_line) * E);
    for (int i = 0; i < S; i++)
    {
        for (int j = 0; j < E; j++)
        {
            cache[i][j].valid_bit = 0;
            cache[i][j].tag = cache[i][j].stamp = -1; 
        }
    }
}

void destroy()
{
    for (int i = 0; i < S; i++)
        free(cache[i]);
    free(cache);
}

void update(unsigned addr)
{
    int s_addr = (addr >> b) & ((-1U) >> (32 - s));
    int t_addr = (addr >> (s + b));
    // 缓存命中
    for (int i = 0; i < E; i++)
    {
        if (cache[s_addr][i].tag == t_addr)
        {
            cache[s_addr][i].stamp = 0;
            hit++;
            return;
        }
    }
    // 缓存未命中,还有空块
    for (int i = 0; i < E; i++)
    {
        if (cache[s_addr][i].valid_bit == 0)
        {
            miss++;
            cache[s_addr][i].valid_bit = 1;
            cache[s_addr][i].tag = t_addr;
            cache[s_addr][i].stamp = 0;
            return;
        }
    }
    // 没有空组,产生替换
    miss++;
    eviction++; 
    int max_stamp = 0, max_i = 0;
    for (int i = 0; i < E; i++)
    {
        if (cache[s_addr][i].stamp > max_stamp)
        {
            max_stamp = cache[s_addr][i].stamp;
            max_i = i;
        }
    }
    cache[s_addr][max_i].tag = t_addr; 
    cache[s_addr][max_i].stamp = 0;
    return;
}

void time()
{
    for (int i = 0; i < S; i++)
    {
        for (int j = 0; j < E; j++)
        {
            if (cache[i][j].valid_bit == 1) // 被使用了
                cache[i][j].stamp++;
        }
    }
}

int main(int argc, char* argv[])
{
    int opt;
    while (-1 != (opt = getopt(argc, argv, "s:E:b:t:")))
    {
        switch (opt)
        {
        case 's':
            s = atoi(optarg); // optarg是getopt函数设置的指向当前选项参数的指针
            S = 1 << s;
            break;
        case 'E':
            E = atoi(optarg);
            break;
        case 'b':
            b = atoi(optarg);
            B = 1 << b;
            break;
        case 't':
            filepath = optarg;
            break;
        }
    }
    init();
    FILE* pf = fopen(filepath, "r");
    if (pf == NULL)
    {
        printf("fopen fail\n");
        exit(-1);
    }
    char op;
    unsigned addr;
    int size;
    while (fscanf(pf, "%c %x,%d", &op, &addr, &size) > 0)
    {
        switch (op)
        {
        case 'L':
            update(addr);
            break;
        case 'M':   // 执行两次
            update(addr);
        case 'S':
            update(addr);
            break;
        }
        time();
    }
    destroy();
    fclose(pf);
    printSummary(hit, miss, eviction);
    return 0;
}

在这里插入图片描述

Part B: Optimizing Matrix Transpose

  • 函数功能trans.c中编写transpose_submit函数,计算矩阵的转置并存储结果,尽量减少高速缓存未命中次数。
  • 编程规则编译无警告;每个转置函数最多定义 12 个int类型的局部变量,不能使用long类型变量或位技巧规避此规则;函数不能使用递归;使用辅助函数时,辅助函数和顶级转置函数在栈上的局部变量总数不能超过 12 个;不能修改数组 A,可随意处理数组 B;不能定义数组或使用malloc
  • 提示转置函数在直接映射缓存上评估,冲突未命中是潜在问题,需考虑代码中尤其是对角线上的冲突未命中,设计降低冲突未命中的访问模式。分块是减少缓存未命中的有用技术,可参考利用分块提高时间局部性PDF 获取更多信息。测试程序test - trans会保存函数的跟踪文件(如trace.f0等),可通过参考模拟器的-v选项运行跟踪文件辅助调试。

给大家推荐两个写的好的文章,我做不出来…

myk的Cache Lab和马天猫的Cache Lab笔记。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2251145.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux内核4.14版本——ccf时钟子系统(3)——ccf一些核心结构体

目录 1. struct clk_hw 2. struct clk_ops 3. struct clk_core 4. struct clk_notifier 5. struct clk 6. struct clk_gate 7. struct clk_divider 8. struct clk_mux 9. struct clk_fixed_factor 10. struct clk_fractional_divider 11. struct clk_multiplier 12…

点云处理中obb算法原理和法向量求解方法

主要数学原理PCA PCA&#xff08;Principal Component Analysis&#xff0c;主成分分析&#xff09;是数据分析中的一种重要技术&#xff0c;通过它可以将高维数据投影到低维空间&#xff0c;找到数据的主要结构。在点云分析中&#xff0c;PCA 可以帮助我们提取点云数据中的主…

shell编程7,bash解释器的 for循环+while循环

声明&#xff01; 学习视频来自B站up主 泷羽sec 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&#…

【人工智能】Python常用库-TensorFlow常用方法教程

TensorFlow 是一个广泛应用的开源深度学习框架&#xff0c;支持多种机器学习任务&#xff0c;如深度学习、神经网络、强化学习等。以下是 TensorFlow 的详细教程&#xff0c;涵盖基础使用方法和示例代码。 1. 安装与导入 安装 TensorFlow&#xff1a; pip install tensorflow…

wxFormBuilder:可视化设计、学习wxWidgets自带UI控件的好工具

wxFormBuilder很快就能拼出一个界面&#xff0c;而且可以直接出对应的代码&#xff0c;拷贝到项目里小改一下就能用。

Vim操作

1. Vim的模式 2.正常模式->编辑模式 在上⽅插⼊⼀⾏&#xff1a; O在下⽅插⼊⼀⾏&#xff1a; o (open)在当前光标前插⼊&#xff1a; i在⾏⾸插⼊&#xff1a; I在当前光标后插⼊&#xff1a; a在⾏尾插⼊&#xff1a; A 3.常见命令行 1、拷贝当前行 yy ,拷贝当前行向下…

阿里云服务器(centos7.6)部署前后端分离项目(MAC环境)

Jdk17安装部署 下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/ 选择自己需要的jdk版本进行下载。 通过mac终端scp命令上传下载好的jdk17到服务器的/usr/local目录下 scp -r Downloads/jdk-17.0.13_linux-x64_bin.tar.gz 用户名服务器ip地址:/us…

「Mac畅玩鸿蒙与硬件33」UI互动应用篇10 - 数字猜谜游戏

本篇将带你实现一个简单的数字猜谜游戏。用户输入一个数字&#xff0c;应用会判断是否接近目标数字&#xff0c;并提供提示“高一点”或“低一点”&#xff0c;直到用户猜中目标数字。这个小游戏结合状态管理和用户交互&#xff0c;是一个入门级的互动应用示例。 关键词 UI互…

Python系列 - MQTT协议

Python系列 - MQTT协议 资源连接 MQTT的介绍和应用场景的示例说明 一、什么是MQTT 百度关于MQTT的介绍如下&#xff1a; MQTT(消息队列遥测传输)是ISO 标准(ISO/IEC PRF 20922)下基于发布订阅范式的消息协议。它工作在 TCP/IP协议之上&#xff0c;是为硬件性能低下的远程设…

ipad项目 蓝湖宽度

ipad项目 横屏状态时 蓝湖宽度设置930px media screen and (orientation: portrait) {/* 竖屏时的样式 */ } media screen and (orientation: landscape) {/* 默认是 横屏时的样式 */ }

理解Java集合的基本用法—Collection:List、Set 和 Queue,Map

本博文部分参考 博客 &#xff0c;强烈推荐这篇博客&#xff0c;写得超级全面&#xff01;&#xff01;&#xff01; 图片来源 Java 集合框架 主要包括两种类型的容器&#xff0c;一种是集合&#xff08;Collection&#xff09;&#xff0c;存储一个元素集合&#xff08;单列…

搭建深度学习框架+nn.Module

一、搭建项目框架&#xff08;YOLO框架的简约版本&#xff09; 最终成品的项目框架如下图&#xff0c;最终实现的效果&#xff0c;通过自己配置的框架函数&#xff0c;对模型进行定义与参数调配。同时在参数配置的过程中可选择是否进行模型初始化参数的使用。适用于YOLO框架的…

FFmpeg 简介与编译

1. ffmpeg 简介&#xff1a; FFmpeg是一套可以用来记录、转换数字音频、视频&#xff0c;并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec&#xff0c;为了保证高可移…

打latex公式可以练到像手写一样快吗?

这里分享两个Python Latex工具latexify和handcalcs。 latexify生成LaTeX 数学公式 import math import latexify @latexify.with_latex #调用latexify的装饰器 def solve(a, b, c):return (-b + math.sqrt(b**2 - 4*a*c)) / (2*a)solve 更多例子.......

【Linux】磁盘 | 文件系统 | inode

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;青果大战linux 总有光环在陨落&#xff0c;总有新星在闪烁 模电好难啊&#xff…

AntFlow 0.20.0版发布,增加多数据源多租户支持,进一步助力企业信息化,SAAS化

传统老牌工作流引擎比如activiti,flowable或者camunda等虽然功能强大&#xff0c;也被企业广泛采用&#xff0c;然后也存着在诸如学习曲线陡峭&#xff0c;上手难度大&#xff0c;流程设计操作需要专业人员&#xff0c;普通人无从下手等问题。。。引入工作流引擎往往需要企业储…

Scrapy管道设置和数据保存

1.1 介绍部分&#xff1a; 文字提到常用的Web框架有Django和Flask&#xff0c;接下来将学习一个全球范围内流行的爬虫框架Scrapy。 1.2 内容部分&#xff1a; Scrapy的概念、作用和工作流程 Scrapy的入门使用 Scrapy构造并发送请求 Scrapy模拟登陆 Scrapy管道的使用 Scrapy中…

洛谷 B3626 跳跃机器人 C语言 记忆化搜索

题目&#xff1a; https://www.luogu.com.cn/problem/B3626 题目描述 地上有一排格子&#xff0c;共 n 个位置。机器猫站在第一个格子上&#xff0c;需要取第 n 个格子里的东西。 机器猫当然不愿意自己跑过去&#xff0c;所以机器猫从口袋里掏出了一个机器人&#xff01;这…

docker快速部署gitlab

文章目录 场景部署步骤默认账号密码效果 场景 新增了一台机器, 在初始化本地开发环境&#xff0c;docker快速部署gitlab 部署步骤 编写dockerfile version: 3.7services:gitlab:image: gitlab/gitlab-ce:latestcontainer_name: gitlabrestart: alwayshostname: gitlabenviron…

计算机视觉工程师紧张学习中!

在当今这个日新月异的科技时代&#xff0c;计算机视觉作为人工智能的重要分支&#xff0c;正以前所未有的速度改变着我们的生活和工作方式。为了紧跟时代步伐&#xff0c;提升自我技能&#xff0c;一群怀揣梦想与热情的计算机视觉设计开发工程师们聚集在了本次线下培训活动中。…