CMU15445(2025 Fall) lab PROJECT #0 - C++ PRIMER + 环境配置(VS2026+WSL2)

文章目录

前言

发现前几年做的15445内容忘得差不多了,最近再来搓一遍玩玩。

由于教授要求非public,本博客将不会出现完整代码,顶多出现代码片段。

项目依旧基于C++17构建,现在看来当年算新鲜的标准已经有点落后了()

相关链接

官方网站

之前做23Spring的环境配置
FAQ(发现这个版本还专门提了池先森。。)

相关环境

配置:14700K + 64G

IDE:Visual studio 2026 insiders

主机环境:Windows11

Linux环境:WSL2 + Ubuntu24.04

0. 环境配置

本次选用Visual Studio配合WSL2搭建环境,关于VS,安装这个东西:

Github仓库

然后拉仓库,参考官方链接

首先创建一个私有库

记下来URL:

WSL配置

在WSL里创一个文件夹,然后拉公共仓库并镜像到自己的仓库:

bash 复制代码
git clone --bare https://github.com/cmu-db/bustub.git bustub-public
cd bustub-public
git push git@github.com:JMC2002/15445_25Fall.git master # 记得换成你自己的!

删除本地克隆,拉取自己的,这里建议用https,不然很慢

bash 复制代码
cd ..
rm -rf bustub-public 
git clone https://github.com/JMC2002/15445_25Fall.git # 记得换成你自己的!

将公共仓库添加为第二个远程用来更新:

bash 复制代码
git remote add public https://github.com/cmu-db/bustub.git

git remote -v

拉取公共仓库的更改,这样更新:

bash 复制代码
git pull public master

由于是私有仓库,我们禁用Action,免得用完配额

然后我们运行脚本安装必要的包:

bash 复制代码
sudo build_support/packages.sh

构建:

bash 复制代码
mkdir build
cd build
cmake ..
make

这里提一下,这个年份默认是用的clang15,如果你想要别的版本的话就同时改一下安装脚本和cmake:

另外,这里可能会跳一个警告,说你的编译器用的不是clang-15怎么怎么样,就手动指定一下编译器再make:

复制代码
cmake .. -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15
make

此外,make的时候默认是单线程,很慢,可以这样线程拉满编译:

bash 复制代码
rm -rf build
mkdir build && cd build

cmake .. -DCMAKE_C_COMPILER=clang-15 -DCMAKE_CXX_COMPILER=clang++-15

make -j$(nproc)

单线程的时候用了两分多钟

这里开了28线程半分钟就搞好了:

本地测试:

bash 复制代码
make check-tests

由于还没开始写,会报错,这是正常的,后面我们就用这个测试。

Visual Studio

VS直接打开WSL的项目的话会卡卡的,不好用,这里我们在Windows里再拉一份,刚刚我们做好了自己的仓库,这里直接克隆下来:

接下来,我们在Windows上用VS打开,选择打开文件夹,比如我这是\\wsl.localhost\Ubuntu\home\jmc\15445_25fall\15445_25Fall

在打开后,可能啥也看不见,这个时候我们在解决方案资源管理器里选择文件夹视图:

这时候可能会扫描到我们的CMake然后弹配置,如果没弹的话就找到本地文件夹,然后删掉.vs后再打开这个文件夹试试

选择我们需要的WSL主机:

然后在设置里选择始终使用CMake预设

这里会默认给一个Linux-Debug,我们点这个管理配置

插入这样一段,其中,debug模式下开启了"BUSTUB_SANITIZER": "address,leak"

json 复制代码
    {
      "name": "wsl-clang-debug",
      "displayName": "WSL: Ubuntu (Clang Debug)",
      "description": "在WSL上使用Clang15",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/out/build/${presetName}",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Debug",
        "BUSTUB_SANITIZER": "address,leak",
        "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
        "CMAKE_C_COMPILER": "clang-15",
        "CMAKE_CXX_COMPILER": "clang++-15"
      },
    {
      "name": "wsl-clang-release",
      "displayName": "WSL: Ubuntu (Clang Release)",
      "description": "在WSL上使用Clang15",
      "generator": "Ninja",
      "binaryDir": "${sourceDir}/out/build/${presetName}",
      "cacheVariables": {
        "CMAKE_BUILD_TYPE": "Release",
        "CMAKE_INSTALL_PREFIX": "${sourceDir}/out/install/${presetName}",
        "CMAKE_C_COMPILER": "clang-15",
        "CMAKE_CXX_COMPILER": "clang++-15"
      },
      "environment": {
      },
      "condition": {
        "type": "equals",
        "lhs": "${hostSystemName}",
        "rhs": "Linux"
      },
      "vendor": { "microsoft.com/VisualStudioRemoteSettings/CMake/2.0": { "remoteSourceRootDir": "$env{HOME}/.vs/$ms{projectDirName}" } }
    },

随便选一个启动项,比如bustub-shell

运行,然后发现跳了个异常,因为我们没实现,说明环境配置大功告成,可喜可贺!

这时候我们发现git不可信任:

我们右键信任即可。

然后就可以做第一个提交了:

然后在Git>管理远程仓库中添加一个public用来拉取公共库的更新,提取写https://github.com/cmu-db/bustub.git,推送也可以写这个(反正也推不上去,不用管):

或者也可以Ctrl+ˋ打开命令行,然后直接执行前面那几个命令拉取:

注册账号

gradescope注册个号,点击右上角Sign Up
Student

课程号填5R4XPZ(2025Fall),学校填Carnegie Mellon University,填好其他信息及邮件,会给你的邮箱发送一封设置密码的邮件,密码要求最短12位。这个验证码是专门提供给非CMU学生的,来自FAQ

弄好后是这样的,可以提交:

1. Project 0

OK,终于可以开始做Project0了,这里我会详细演示一下工作流,以及简单点评一下这个Project。

签出分支

我们做每一个project前,先签出一个分支,做完后再合并回master(因为后一个project往往强依赖于前一个),这样避免把代码搞乱

作业背景

这次的p0与前几次大相径庭,是做一个并发数据结构

先给了你一个背景,假设你是一个网站管理员,现在你想找哪个IP的访问量最大,最直接的想法是用一个哈希表(ip, cnt)去存每个IP对应的访问次数,但这在数据量很大的时候占用的内存是非常高的,于是引入了CM Sketch这个东西。

这个是一种概率数据结构,简单来说,前面哈希表存的key太多,那我直接不存key本身,改为直接维护哈希值的计数,这样就省去了很大的内存开销,但是很显然,哈希函数是有冲突的,因此我们可以在每一个IP插入的时候,做depth次哈希,给每次哈希算出来的哈希值加一个计数,在要查询的时候再次做depth次哈希,找到里面的最小值,认为这个最小值就是我们IP的计数,这样尽管严格来说还是不完全准确,但可以得到一个相对准确的计数值。

内存上,假设我们把哈希值(比如取模之类的、相当于再做一次哈希)约束到width内,我们只需要维护一个w*d的二维数组,就减少了很多内存。

Task

然后看一下任务,我们要实现的就是一个构造函数(带参+移动构造)、一个移动赋值、插入、查询、清除、合并、查询TopK

有几点注意事项是要使用他提供的哈希函数、在做插入时要线程安全,同时还要杜绝一把大锁锁完的情况,锁尽量细粒度或者无锁

文件

我们要写的就是这个count_min_sketch.h/count_min_sketch.cpp

一些细节

  • 我们可以存一个std::unique_ptr<std::atomic<uint32_t>[]> table_;,就可以避免使用锁了
  • Top-k的时候,可以使用std::nth_element+std::sort,先做快选再排k,这样的时间复杂度是 O ( n + k log ⁡ k ) O(n+k\log k) O(n+klogk),类似的可以用std::partial_sort,这样的时间复杂度是 O ( n log ⁡ k ) O(n\log k) O(nlogk),考虑到 k k k一般比较小,还是选前者比较好
  • 原始的哈希函数产生器是捕获的this指针,在做移动的时候,如果直接std::move哈希函数数组就会导致垂悬引用,因此我们在捕获的时候改为值捕获width即可

提交代码

写完代码后,我们选择count_min_sketch_test

如果没问题的话,在远程控制台就能看到测试通过的输出以及跑分

这个时候正常就该跑一下clang-tidy的检查了

bash 复制代码
make format
make check-clang-tidy-p0

我们打开终端、选择WSL,正常应该启动就在这个目录,或者在外面开一个终端也行:

打开~/.vs/15445_25Fall/out/build(这个路径对应之前填的地方)

然后打开对应的文件,进去就可以看到cmake生成的文件了

由于我们之前用的生成器是ninja,因此这里执行:

bash 复制代码
ninja format
ninja check-clang-tidy-p0

最后不报错就说明检查通过:

关于内存泄漏检测,如果你使用前面我提供的设置,换用Debug跑一下能过就行。

另外,值得注意的一点是,提交要求UTF-8,右下角这里如果不是UTF-8的话需要手动保存成UTF-8(无签名)

此外,不知道为什么直接本地format不会应用头文件顺序的检查,因此最好手动把头文件按字母顺序排列一下,免得提交上去格式检查不通过。

一切无误后,生成一个提交

bash 复制代码
ninja submit-p0

如果是全新的环境,可能需要安装zip

bash 复制代码
sudo apt update
sudo apt install zip

然后可以看见生成了一个zip到(生成的)项目根目录下

然后提交

提交上去后会自动给你打分

等一会后就会显示是否通过/哪个地方没通过:

合并分支

通过后就可以合并分支了,先推送更改:

然后切换到master,再右键p0,合并到当前分支:

顺便还能打一个tag:

3. 结语

本文也算开了个头,演示了一下这个东西的基本工作流程,后面应该就不会把工作流写这么细了。

相关推荐
DBA小马哥3 小时前
Oracle迁移实战:如何轻松跨越异构数据库的学习与技术壁垒
数据库·学习·oracle·信创·国产化平替
暮乘白帝过重山4 小时前
ArkTS ForEach 参数解析:组件与键值生成器
开发语言·数据库
LiamTuc4 小时前
Java构造函数
java·开发语言
三途河畔人4 小时前
Pytho基础语法_运算符
开发语言·python·入门
Benmao⁢4 小时前
C语言期末复习笔记
c语言·开发语言·笔记·leetcode·面试·蓝桥杯
adsadswee4 小时前
Qt 样式与 QLinearGradient 渐变详解
开发语言·qt·qt样式表·qlineargradient·qss渐变效果
菜鸟plus+4 小时前
N+1查询
java·服务器·数据库
子夜江寒4 小时前
MySQL 表创建与数据导入导出
数据库·mysql
花月C4 小时前
个性化推荐:基于用户的协同过滤算法
开发语言·后端·算法·近邻算法
菜鸟小九5 小时前
redis基础(安装配置redis)
数据库·redis·缓存