2022 CMU15-445 Project 1 Buffer Pool

news2024/11/18 4:43:37

通过截图

image.pngimage.png

image.png
image.png

Task #1 - Extendible Hash Table

该 task 的知识点名为 可扩展动态散列
https://cloud.tencent.com/developer/article/1020586
这个部分要实现一个 extendible 哈希表,内部不可以用 built-in 的哈希表,比如 unordered_map。这个哈希表在 Buffer Pool Manager 中主要用来存储 buffer pool 中 page id 和 frame id 的映射关系。
这里的算法我在课上没听懂太多,感觉给的图不是特别清晰,项目中给的 IndexOf函数,是根据低位来进行判断。

须知

要完成这个 task 首先要明确 可拓展散列 的概念,其中有 几 个关键名词,目录,桶,全局位深度和局部位深度,

  1. 首先是目录,目录就是存放着桶指针的表,和一些元信息,可以看作为中控台。
  2. 桶,就是用来存放数据的。
  3. 全局位深度,这里写作 G ,可以看作目录中最多有 2 的 G 次方个桶。
  4. 局部位深度,这里写作 L ,是桶特有的,每个桶独自保存一个 L,这代表该桶中元素的 key 的哈希值的后 L 位是相等的,后面主要用于桶的分裂,这里没有概念很正常。

这里就讲一个该 task 中最难实现的方法,插入:

  1. 首先,初始深度为0,你哈希后取 index 只能为0image.png
  2. 接着插入 2 个,桶的大小在项目中是有规定的,故这里取2来讲。

image.png

  1. 再插入第三个时,桶满了,此时 L == G,则采用这种策略image.png

这里解释一下兄弟项,其实就是目录翻倍后,多出来的一倍,和原来的一倍按顺序一一对应即可,至于原理则是,翻倍后,这2部分的索引的二进制表达的第 G 位,分别为 1 ,0.(下图中便有)
image.png

  1. 之后若有情况如,L < G 的 如下图中b桶如果要接着插入:


则说明存在指向相同的桶,此时不需要更新 G,只需要更新 L 并将兄弟项指向的桶进行新建,再进行 kv 重排列便可

代码

void ExtendibleHashTable<K, V>::Insert(const K &key, const V &value) {
  std::scoped_lock<std::mutex> lock(latch_);
  // 先保存着 ,待会随着深度变化,再次调用结果可能会不一致
  auto index = IndexOf(key);
  auto bucket = dir_[index];
  // 有剩余空间则直接插入
  if (bucket->Insert(key, value)) {
    // 这里是唯一正确的出口
    return;
  }
  // 开始重整
  // 若局部深度等于全局深度,则更新全局深度与目录容量
  if (bucket->GetDepth() == GetGlobalDepthInternal()) {
    size_t len = dir_.size();
    dir_.reserve(2 * len);
    std::copy_n(dir_.begin(), len, std::back_inserter(dir_));
    global_depth_++;
  }
  // 莫名其妙到这里 item 失效了 原来是 vec 的自动扩容,导致本来的地址不能用了要重新获取 bucket, index
  // 也会变,要用之前的
  bucket = dir_[index];
  // 若局部深度小于全局深度,则更新局部深度并拿个新 Bucket 用
  if (bucket->GetDepth() < GetGlobalDepthInternal()) {
    // 开始分裂
    auto bucket0 = std::make_shared<Bucket>(bucket_size_, bucket->GetDepth() + 1);
    auto bucket1 = std::make_shared<Bucket>(bucket_size_, bucket->GetDepth() + 1);
    num_buckets_++;
    // 点睛之笔 比如 当前深度为 1,你不可能 把 1 左移 1位去判别兄弟节点,你应该把有效位的最后一位拿来
    int mask = 1 << bucket->GetDepth();
    for (auto &[k, v] : bucket->GetItems()) {
      size_t hashkey = std::hash<K>()(k);
      // 根据本地深度表示的有效位最后一位判别,若为 1,插入新建的那个bucket
      if ((hashkey & mask) != 0) {
        bucket1->Insert(k, v);
      } else {
        // 根据本地深度表示的有效位最后一位判别,若为 0,插入原有的 bucket
        bucket0->Insert(k, v);
      }
    }
    // 减少不必要的遍历,从前一位的大小开始,若是 0 则从 0 开始 ,若是 1 ,则可以节省很多,兄弟节点这一位肯定是一样的
    for (size_t i = index & mask - 1; i < dir_.size(); i += mask) {
      // 根据本地深度表示的有效位最后一位判别,若为 1,取代新建的那个bucket
      if ((i & mask) != 0) {
        dir_[i] = bucket1;
      } else {
        // 根据本地深度表示的有效位最后一位判别,若为 0,取代原有的 bucket
        dir_[i] = bucket0;
      }
    }
    latch_.unlock();
    // 递归插入本来要插入的值
    Insert(key, value);
    latch_.lock();
  }
}

这里讲我卡很久的一个点

  1. Insert 的时候先找是否已存在 若存在直接覆盖值就好了 就是因为顺序错了导致线上测试才没过

Task #2 - LRU-K Replacement Policy

该 task 的知识点名为 LRU-K算法
https://blog.csdn.net/love254443233/article/details/82598381
这个部分要实现一个 LRU-K 替换器,比刚刚简单多了,看懂了上面文章,另外再替换策略上加一层:先排除用的最少的缓存,缓存一样便排除最久未使用的缓存,这里意味着可能要用时间戳。测试后发现只要移动队列中元素位置便可,无需时间戳。历史队列和缓存队列我都采取了 list结构进行实现,因为好进行二次排序,再使用 hashmap 来进行 o(1) 的查找。
以下展示部分代码:

void LRUKReplacer::RecordAccess(frame_id_t frame_id) {
  std::lock_guard<std::mutex> lock_guard(latch_);
  BUSTUB_ASSERT((size_t)frame_id <= replacer_size_, true);
  size_t new_times = ++map_[frame_id].times_;
  // 新元素
  if (new_times == 1) {
    // std::cout << "插入frame " << frame_id << " count: " << map_[frame_id].times_ << std::endl;
    history_list_.emplace_front(frame_id);
    map_[frame_id].pos_ = history_list_.begin();
  } else {
    if (new_times == k_) {
      history_list_.erase(map_[frame_id].pos_);
      cach_list_.emplace_front(frame_id);
      // 更新索引
      map_[frame_id].pos_ = cach_list_.begin();
    } else if (new_times > k_) {
      // 已在缓存队列,更新位置
      cach_list_.erase(map_[frame_id].pos_);
      cach_list_.emplace_front(frame_id);
      // 更新索引
      map_[frame_id].pos_ = cach_list_.begin();
    }
  }
}

这里也讲一个卡了我很久的点

  • RecordAccess时达到k_ 次,放入缓存队列 ,记住若小于 k_ 次,访问不会改变位置,按第一次来,因为这个所以才通不过在线测试,且缓存的evictable_应该初始化为false, 否则影响测评

Task #3 - Buffer Pool Manager Instance

该 task 的知识点名为 Buffer Pool Manager
该 task 概念比较容易,就讲一下我卡住的几个点

  1. 当你实现 FetchPgImp时,记住,若返回已经存在的 framepage 时,也要记得将 将Evictable设置为 false
  2. UnpinPgImp中关于修改 is_dirty部分,只能从 false -> true 修改,true->false 只能写回后才能修改
  3. FlushPgImp函数不需要管 is_dirty直接写回,然后更新信息
  4. 当你进入一个函数时,一定要做完所有工作再交出锁,否则你永远不知道抢到该锁的是不是你想交给的那个函数。

以下展示部分代码:

// 该函数 NewPgImp 和 FetchPgImp 都用得到
auto BufferPoolManagerInstance::GetFrame(frame_id_t *frame_id) -> bool {
  frame_id_t fid;
  if (!free_list_.empty()) {
    fid = free_list_.front();
    free_list_.pop_front();
    *frame_id = fid;
    return true;
  }
  if (replacer_->Evict(&fid)) {
    // std::cout << "Evict page: " << pages_[fid].GetPageId()<< std::endl;
    if (pages_[fid].IsDirty()) {
      disk_manager_->WritePage(pages_[fid].GetPageId(), pages_[fid].GetData());
      pages_[fid].is_dirty_ = false;
    }
    page_table_->Remove(pages_[fid].GetPageId());
    *frame_id = fid;
    pages_[fid].pin_count_ = 0;
    pages_[fid].ResetMemory();
    return true;
  }
  return false;
}

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

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

相关文章

Open-Dis的C++版本编译(CMake-gpu 3.21.4)以及SDL2和SDL_net库的配置使用

目录Open-DisOpen-Dis简介分布式交互仿真更多资料Open-Dis下载CMake编译教程SDL2和SDL_netSDL介绍下载SDL配置SDL2下载SDL_net配置SDL_net工程编译Open-DisOpen-Dis Open-Dis简介 Dis是国防部&#xff0c;北约和联合国实时/虚拟世界建模和仿真中使用最广泛的协议之一。 Open-…

关于二进制

关于二进制 读《程序是怎样跑起来的》 用二进制表示计算机信息的原因 计算机内部是由IC&#xff08;集成电路&#xff09;这种电子部件构成的。CPU和内存也是IC的一种&#xff0c;IC有几种不同的形状&#xff0c;有的像一条黑色的蜈蚣&#xff0c;在其两侧有数个乃至数百个引脚…

智慧水务:数字孪生污水处理厂,3D可视化一键管控

近年来&#xff0c;智慧水务、数字水务成为水务行业的热点领域。对于污水处理领域&#xff0c;如何贯彻落实双碳战略&#xff0c;积极推进智慧水厂建设&#xff0c;显得尤为关键。 可视化技术结合视频融合、BIM、5G、物联网、云计算及大数据等先进技术&#xff0c;围绕水质达标…

用DIV+CSS技术制作个人博客网站(web前端网页制作课期末作业)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

【Docker】搭建MySQL主从复制,详细的图文展示

Docker是基于Go语言实现的云开源项目。Docker的主要目标是**“Build&#xff0c;Ship and Run Any App,Anywhere”**。也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理&#xff0c;使用户的APP&#xff08;可以是一个WEB应用或数据库应用等等&#xff09;及其运…

[附源码]JAVA毕业设计计算机散件报价系统(系统+LW)

[附源码]JAVA毕业设计计算机散件报价系统&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技…

技巧 | Python绘制2022年卡塔尔世界杯决赛圈预测图

文章目录&#x1f3f3;️‍&#x1f308; 1. 世界杯三十二强&#x1f3f3;️‍&#x1f308; 2. 世界杯十六强&#x1f3f3;️‍&#x1f308; 3. 世界杯八强&#x1f3f3;️‍&#x1f308; 4. 世界杯四强&#x1f3f3;️‍&#x1f308; 5. 决赛圈&#x1f3f3;️‍&#x1f…

技术内幕 | 阿里云EMR StarRocks 极速数据湖分析

作者&#xff1a;阿里云智能技术专家 周康&#xff0c;StarRocks Active Contributor 郑志铨&#xff08;本文为作者在 StarRocks Summit Asia 2022 上的分享&#xff09; 为了能够满足更多用户对于极速分析数据的需求&#xff0c;同时让 StarRocks 强大的分析能力应用在更加广…

【温故而知新】构建高可用Linux服务器(三)

时间&#xff1a;2022年12月02日 作者&#xff1a;小蒋聊技术 邮箱&#xff1a;wei_wei10163.com 微信&#xff1a;wei_wei10 前言 大家好&#xff0c;欢迎来到小蒋聊技术。小蒋准备和大家一起聊聊技术的那些事。 今天小蒋继续坚持“温故而知新”的落地实践&#xff0c;继续…

[附源码]计算机毕业设计影院管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【单片机基础】C51语言基础

文章目录1、使用C/C开发单片机的优点2、C51中的基本数据类型3、C51数据类型扩展定义4、C51中的运算符与基础语句5、二进制与十六进制转换1、使用C/C开发单片机的优点 C/C语言作为一种非常方便的语言得到了广泛的支持&#xff0c;如STC、STM32、arduino、乐鑫科技的单片机都支持…

【目标搜索】基于matlab运动编码粒子群算法优化 (MPSO) 无人机搜索丢失目标【含Matlab源码 2254期】

⛄一、运动编码粒子群算法简介 1 粒子群算法 PSO算法是一种基于群体智能的随机优化方法。在PSO中&#xff0c;粒子群模拟鸟群行为在搜索空间中探索&#xff08;全局搜索&#xff09;和开发&#xff08;局部搜索&#xff09;&#xff0c;最终找到全局最优解。粒子的速度和位置更…

网络安全观察报告 攻击态势

设备类漏洞从未缓解 从图 5.1 中可以看到&#xff0c;针对设备漏洞的攻击占全部利用漏洞攻击的 43%&#xff0c;这和近两年智能路由器等 联网设备大规模增长密切相关。正如绿盟科技在《2017 年物联网报告》1 中提到的那样&#xff0c;很多智能设备 在设计之初&#xff0c;安全…

第3章 Thymeleaf模板渲染

文章目录第3章 Thymeleaf模板渲染3.2 Thymeleaf编程起步3.4 读取资源文件3.5 路径处理3.6 内置对象操作支持3.7 对象输出3.8 页面逻辑处理3.9 数据迭代处理3.10 包含指令3.11 Thymeleaf数据处理3.12 本章小结3.12 本章小结第3章 Thymeleaf模板渲染 3.2 Thymelea…

【OpenCV-Python】教程:3-13 Hough直线变换

OpenCV Python Hough直线变换 【目标】 理解Hough变换的概念学会使用Hough变换检测直线cv2.HoughLines(), cv2.HoughLinesP() 【理论】 Hough 变换是一个非常有用的技术&#xff0c;可以检测任何形状&#xff0c;只要那个形状可以通过数学方程表示出来&#xff0c;即使检测…

[附源码]计算机毕业设计springboot小区疫情事件处理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

传感器_三相-双极性-开关型-霍尔传感器 速度+电角度解算理解

1 前言 最近项目上涉及到使用三相-双极性-开关型-霍尔传感器解算 电机转速 、电角度的问题。结合自己的理解请教前辈&#xff0c;终有所得&#xff0c;下面做一个学习的记录。 主要以思路为主&#xff0c;不涉及代码。 2 正文 2.1 什么是三相&#xff1f; 所谓三相-双极性-…

毕设项目 - SSM农业商品信息管理权限后台子系统(含源码+论文)

文章目录1 项目简介2 实现效果2.1 界面展示3 设计方案3.1 概述3.2 系统流程3.3 系统结构设计4 项目获取1 项目简介 Hi&#xff0c;各位同学好呀&#xff0c;这里是M学姐&#xff01; 今天向大家分享一个今年(2022)最新完成的毕业设计项目作品&#xff0c;【基于SSM的农业商品…

(算法设计与分析)第四章贪心算法-第一节:贪心算法概述

文章目录一&#xff1a;贪心算法&#xff08;1&#xff09;概述&#xff08;2&#xff09;特点&#xff08;3&#xff09;框架二&#xff1a;典型贪心算法问题&#xff08;1&#xff09;无重叠区间①&#xff1a;题目描述②&#xff1a;解题思路③&#xff1a;完整代码&#xf…

【Android App】人脸识别中扫描识别二维码实战解析(附源码和演示 超详细)

需要源码请点赞关注收藏后评论区留言私信~~~ 一、扫描识别二维码 不仅可以利用zxing库生成二维码&#xff0c;同样利用zxing库可以扫描二维码并解析得到原始文本&#xff0c;此时除了给build.gradle添加如下一行依赖配置 implementation com.google.zxing:core:3.4.1 还需要…