RecIS 开发了一个低内存开销、高效查表、动态扩展、强大稳定的哈希表,规避了 torch.nn.Embedding 的问题。RecIS 内部叫 HashTable,也就是广义上的 Embedding。在本文中,会对 HashTable 的底层实现一探究竟,看看它如何达到的:
- 降低 Embedding 表的内存、通信开销
- 快速查表
- 当 id 增加时,需要动态扩表,且无明显消耗
- 整个系统需要稳定、简洁
RecIS 开发了一个低内存开销、高效查表、动态扩展、强大稳定的哈希表,规避了 torch.nn.Embedding 的问题。RecIS 内部叫 HashTable,也就是广义上的 Embedding。在本文中,会对 HashTable 的底层实现一探究竟,看看它如何达到的:
离开米子后,从相机转行到了搜广推方向,所以需要了解一下搜广推的算法背景。搜索、广告、推荐这三个算法由于背景相似,所以会经常被放到一起。打开 app 时的搜索,刷 app 时的推荐,以及投放用户可能有兴趣的广告。三者的本质几乎是一样的:根据用户喜好,尽可能的在数据库中检索出用户想要的东西,这个东西可能是视频,可能是商品,可能是网页等等。搜广推算法直接和用户点击率挂钩,相当于和收益挂钩,也是互联网中最接近钱的算法。
22 年校招面字节的时候,面试官随口问了个问题:有几亿条数据存储在文件中,我该怎么排序?虽然在很多高频面经上看过这个问题,但完全没有在意,心想:正常排序呗还能怎么做,加载不进内存就分块处理。可具体怎么分块并没有仔细思考过。看似是一个算法题,但这完全是一个工程题。
今年遇到了类似的问题,有两组文件,第一组叫 bench,有 32 个文件,这些文件大约 1T 左右。每个文件里存储着搜推广的稀疏数据,id 和 embedding,每一个 id 对应一个 embedding 数据。第二组文件叫 test,有 8 个文件,这些文件同样约 1T 左右,同样存储了 id 和 embedding。这些 id 和对应的 embedding 完全乱序分布在文件中,毫无规律。
目标:遍历 bench 中的每个 id 和对应的 embedding,在 test 中查找对应的 id 和 embedding,判断是否相等。如果 id 不存在或者 embedding 不相等,打印出错的 id。
从今年春节回来到现在,经历了不少事情。暑期勉强打赢了“复活赛”,不过主包也快到残血状态了。现在终于能腾出点时间,好好学习一下。
有很多想学的东西,技术方向包括 vllm、deepspeed、大模型、CUDA、模型量化等;非技术方面,想学剪视频和修图——毕竟手里攒了一堆素材,哈哈哈,慢慢来吧。
今天想聊聊信号量,这也是我在新工作中遇到的实际场景。信号量本质上是一个变量,常用于多线程环境中的同步控制。举个例子:假设有两个线程 A 和 B,A 在处理临界资源,当满足某些条件时,它会释放锁并通知 B;而 B 完全没必要一直轮询 “A 做完了吗?”。这样既浪费资源,又不够优雅。
就用 C++ 代码告别吧:
1 | auto others.todo = std::move(my.work); |
离职不是失败,而是换了一种选择。 其实我一直在等,等 leader 说一句:jw 你最近经常不在工位,是不是有什么想法;等 leader 说一句我给你机会,你好好工作今年给你晋升。我想了很多回答,也许是顺从也许是争论,但直到离职那天也没等到。
最近这半年实在是闲,秉承着下班少玩手机的目的,7 月开始学 cuda,8 9 月学了 C++,10 月懈怠了一个月,11 月学了 cuda 进阶,12 月我来祸害 nndeploy 了。
一来是学完 C++ 后看下我能看懂的优秀的开源项目,一方面在之前学校训练模型感觉没意思,是看看 AI 的工程化。
利用下班时间学完了 CUDA,Anyway 忙起来真的很大程度能缓解焦虑,能忘记和忽略很多烦恼。所以寻思着结合这一年来所学,写了一个简单的 CUDA 计算框架:CUFX。