当前位置: 首页 > news >正文

CMU-15445(2024fall)——PROJECT#0

题目介绍

这是题目原文。
注意:在拉取项目的时候需要注意拉取2024fallTag,本人血泪教训!

本题是关于HyperLogLog的具体实现,其介绍可以看这个视频进行了解。简单来说HyperLogLog可以在一个非常小的固定内存下(一般为十几KB)非常快速地估算出大量数据的唯一元素数量,并且其可以分别对多个数据库独立估算,还不会损失精度。

比如要统计访问网站的唯一用户数,如果用精确算法,需要对数据库中的所有数据进行比对,这会占用非常大的内存且非常耗时,尤其是在分布式存储的情况下。但我们在绝大多数的时候并不需要一个精确的值,因此可以使用HLL对其进行估算(虽说是估算,但其误差也非常小)。

这道题主要检查了学生的C++基础,以及对C++项目的开发和调试能力。

文章末尾有本人的项目代码地址,文章内容主要讲述思路和一些细节不会出现代码,大家各取所需。

Task#1

Task#1是实现基本的HLL算法。

所需修改的文件目录为:
src/include/primer/hyperloglog.h
src/primer/hyperloglog.cpp

测试文件的目录为:
test/primer/hyperloglog_test.cpp

原始代码中已经给出了一些变量和方法的定义及实现,需要我们进行完善和补全。

hyperloglog.h中的变量部分给出了最终的结果cardinality_和计算常量CONSTANT,缺少了题目中所提及的bmpbp可以设置为uint8_t类型的参数,因为其值的范围在0到63之间,m可以设置为uint8_t的数组,原因同上。

  • CalculateHash():将传入的值转换为哈希值的方法。
  • GetCardinality():返回最终结果。

hyperloglog.cpp是该算法主要的函数实现。以下是各个方法的简介:

  • HyperLogLog(inital_bits):构造函数,需要我们根据传入的b初始化我们内部的bm
  • AddElem(val):计算出传入值的p并将其存在m中(最主要方法)。
  • ComputeCardinality():根据公式计算最终结果。
  • ComputeBinary():将哈希值转换为64位二进制流。
  • PositionOfLeftmostOne():计算出p值(二进制流中最左侧 1 的位置)。

我这里添加了一个函数GetBucketValue(),用来计算p应该存在m的哪个位置中。

接下来我会大概说一下我的解答中每个方法的实现。

HyperLogLog(inital_bits)

根据传入的b初始化我们内部的bm。需要对b的值进行判断,看是否是小于0的值,如果小于0则直接return,否则对我们内部的b进行赋值。同时需要根据b重新设置我们m的大小。
注意: 如果将b设置为size_t或者unit_t类型,需要注意其数值不会小于0,容易因此产生bug。

ComputeBinary()

可以直接使用std::bitsize<64>()方法,将传入的哈希值转换为64位二进制流。需注意,这里转换后的值第0位是低位,第63位是高位,不要搞反了。

GetBucketValue()

我们需要从后往前获取b位二进制流的内容,计算这个二进制数在十进制下是几。可以通过位操作符<<进行计算。

PositionOfLeftmostOne()

由于Task#1是计算高位1的位置,高位的前b位又被用来计算插入位置。所以我们需要从第63 - b位开始,从高到低查找二进制流第一个1的位置。

AddElem(val)

有了前面几个方法,这个方法实现起来就比较简单了。分别调用前面的几个方法,得到参数的哈希值、64位二进制流、插入m的位置、高位1的位置p,就只需将当前pm上的值比较一下大小,将大的存入就可以了。

ComputeCardinality()

根据公式计算最终结果,可以先算出分母的总数,再计算整个公式,可以使用static_cast<size_t>()方法保留结果的整数部分。进行幂计算时可以使用1.0 / std::pow(2, num)进行计算。

Task#2

要求我们实现HyperLogLog算法的密集布局,整体与Task#1类似,不过这里是从低位开始计算0的数量,并且如果数量超过15,需要将其拆分成高3位和低4位分别进行存储。

所需修改的文件目录为:
src/include/primer/hyperloglog_presto.h
src/primer/hyperloglog_presto.cpp

hyperloglog_presto.h文件多出了dense_bucket_overflow_bucket_两个参数,前者和前面的m基本相同,后者是在发生溢出时存储高3位的桶。

整体思路没有什么变化,只有以下几点需要变化:

  1. PositionOfLeftmostOne()方法需要改为从低到高计算0的个数。
  2. 获取到0的个数p后,需将其拆分为高3位和低4位。可以使用与操作符&进行处理。
  3. 在对比p和插入位置的值,以及计算最终结果时,要将dense_bucket_overflow_bucket_中相应位置的值进行合并,转换为十进制进行比较。转换为十进制可以使用to_ulong()方法,合并操作可以使用或操作符|

测试

先将test/primer/hyperloglog_test.cpp中的测试函数第二个参数的DIABLE_去掉。

mkdir build && cd build
cmake -DCMAKE_BUILD_TYPE=Debug ..
make -j$(nproc) hyperloglog_test
./test/hyperloglog_test

正常应该如图所示:
在这里插入图片描述

提交

cd ..
mkdir build_rel && cd build_rel
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
make format
make check-clang-tidy-p0
make submit-p0

如果有格式问题clang-tidy会报错。我这里本地没有报错,但是提交到平台上就会报格式错误,可能是工具版本的问题。

执行完成后会在根目录生成一个压缩包,上传该压缩包等待平台打分。

正常如图所示:
在这里插入图片描述
代码地址:https://github.com/GCW-kuku/bustub

http://www.dtcms.com/a/286207.html

相关文章:

  • iOS 文件深度调试实战 查看用户文件 App 沙盒 系统文件与日志全指南
  • 【橘子分布式】gRPC(编程篇-上)
  • vue2 面试题及详细答案150道(91 - 100)
  • 人工智能概念之九:深度学习概述
  • kafka 单机部署指南(KRaft 版本)
  • 基于MATLAB的GA遗传算法优化BP神经网络的数据分类预测方法应用
  • 在ComfyUI中CLIP Text Encode (Prompt)和CLIPTextEncodeFlux的区别
  • docker gitlab 备份 恢复 版本升级(16.1.1到18.2.0)
  • SpringAI核心特性与Prompt工程
  • 六个直播回放的功能,助力在线教育蓬勃发展!
  • AR技术重塑电力巡检:效率提升与智能升级
  • Kubernetes (k8s)、Rancher 和 Podman 的异同点分析
  • 题解:CF1617C Paprika and Permutation
  • Redis学习其二(事务,SpringBoot整合,持久化RDB和AOF)
  • MySQL查询优化与事务实战指南
  • 【PTA数据结构 | C语言版】我爱背单词
  • 前端埋坑之element Ui 组件el-progress display:flex后不显示进度条解决方案
  • Java实战:实时聊天应用开发(附GitHub链接)
  • http性能测试命令ab
  • IntelliJ IDEA大括号格式设置:换行改行尾
  • Java 核心工具类 API 详解(一):从 Math 到 Runtime 的实用指南
  • 【AI News | 20250717】每日AI进展
  • 【解码文本世界的“隐形分界线”:Windows与Linux回车换行之谜】
  • 基于单片机智能充电器系统设计
  • 如何检查GitHub上可能潜在的信息泄漏
  • 深入理解 Redis 集群化看门狗机制:原理、实践与风险
  • synchronized锁升级过程【AI笔记,仅供自己参考】
  • Pythonday17
  • 中国1km逐月潜在蒸散发数据集 - matlab按shp批量裁剪
  • lesson17:Python函数之递归、匿名函数与变量作用域