比 Bloom Filter 节省25%空间!Ribbon Filter 在 Lindorm 中的应用

1 前言

Lindorm是一个低成本高吞吐的多模数据库,目前,Lindorm是阿里内部数据体量最大,覆盖业务最广的数据库产品。超高的性能和低RT一直是Lindorm追求的目标,因此Lindorm也在不断地优化和迭代,争取在每个小点上都做到极致。这次,我们的优化的目标放到了Lindorm中的Bloom Filter上。

由于Bloom Filter只需要占用极小的空间,便可以给出”可能存在“和”肯定不存在“的存在性判断,因此可以提前过滤掉许多不必要的数据块,从而节省了大量的磁盘IO。在Lindorm中Get操作就是通过运用低成本高效率的Bloom Filter来过滤掉大量无效的数据块的,从而大幅度降低磁盘IO次数。

Bloom Filter存储在了Lindorm的底层文件LDFile中。在长期的生产观察中,我们发现,Bloom Filter的空间占用远大于其他meta数据。在默认配置的错误率下,基本上100MB数据(压缩后),就会产生1MB以上的BloomFilter,也就是BloomFilter会占掉1%的存储空间。对于磁盘存储空间来说,1%的消耗并不多,但是,由于BloomFilter做为Lindorm读链路上的关键链路,通常需要缓存在内存中才能获得更好地性能。内存资源对Lindorm来说是非常宝贵的资源,对于单机管理上TB数据的Lindorm节点来说,通常只有几GB到几十GB的内存来做缓存。按照通常的规律,上TB的数据会产生几十GB的Bloom Filter,这些Bloom Filter会把缓存占满,导致数据无法进入缓存,会严重影响用户请求的内存命中率。因此,优化Bloom Filter的大小,意味着可以减少内存占用,让缓存能够加载更多用户数据,从而优化Lindorm的读性能。

为了优化BloomFilter, Lindorm也做了不少尝试,比如引入SuRF,但我们发现,在空间占用率上,SuRF并不比BloomFilter有优势。因此,我们把目光转向了2021年的一篇论文《Ribbon filter: practically smaller than Bloom and Xor》。这篇论文提出了一种新的Ribbon Filter,据论文的结论,Ribbon Filter相对Bloom Filter可以节省30%的空间。这个对我们来说是一个非常诱人的结论,节省30%空间意味着可以释放30%的缓存空间,读请求的内存命中率会有很大一部分提升。

Ribbon Filter真的有论文中说的那么神奇吗?带来空间节省的同时,会带来副作用吗?本文将这一全新的Ribbon Filter给大家做一个介绍,然后我们把Ribbon Filter引入了Lindorm中,并测试了Ribbon Filter在实际生产中的真实表现。

2 基本原理

2.1 Bloom Filter

Bloom Filter是Bloom在1970年提出的一种概率数据结构[1],用来快速测试元素是否是集合的成员,存在一定的假阳性率(一般设置为0.01),不可能有假阴性率,即查询返回“可能存在”或者“一定不存在”。可以添加元素到集合中,但不能删除(有改进版本可以实现),添加的元素越多,假阳性率越大。对于给定的假阳性率e和元素数量n,Bloom Filter有一个最佳的空间大小,使得添加元素过程中,保证逐渐变大的假阳性率小于等于e。

Bloom Filter由一个长度为n的01数组array组成。首先会将array数组每个元素初始化设为0,对于集合A中的每个元素w,做k次哈希,每次哈希值都会对n取模得到一个索引,比如第i次哈希,索引

,将array数组中的对应位置置为1,最终array变成了一个部分元素为1的数组。对于待检测元素w同样会做k次哈希得到k个索引,如果数组中对应位置都为1则元素w可能存在集合A中,否者一定不存在。

2.2 Xor Filter

Ribbon Filter是基于Xor Filter做的,在介绍Ribbon Filter之前,得先了解Xor Filter。Xor Filter是Thomas Mueller Graf和Daniel Lemire在2020年提出的[2],也是用来检测一个元素是不是集合中的一个成员,相比Bloom Filter,Xor Filter核心差异主要是如下:

  • Xor Filter有固定的三个哈希函数,而Bloom Filter哈希函数由假阳性率确定;
  • Xor Filter采用XOR方式按slot匹配,Bloom Filter使用AND方式进行按位匹配;
  • Xor Filter由一个二维bit数组组成,Bloom Filter是一个一维bit数组;
  • Xor Filter相比Bloom Filter最高能节省20%的空间。

输入的元素经过多个哈希函数生成的哈希值不会像Bloom Filter一样映射到一个bit位,而是映射到一个固定长度的slot,一个slot有多个bit位,且每个slot的bit位数相同。对于待检测元素w,会经过k个哈希函数生成k个哈希值分别映射到对应slot上,然后对所有的k个slot中的元素进行异或运算得到结果r,元素w还会经过另外一个独立的哈希函数生成指纹fingerprint(w),和r作对比,如果相同则元素w可能存在集合A中,否者一定不存在。

接下来介绍Xor Filter的构造原理

开始先介绍几个关键变量:

  • B存放着的r-bit的Xor Filter
  • n是参与构建Xor Filter的集合A元素数量
  • k是哈希函数的个数(固定值3)
  • m是slot的个数

初始时令r=5,n=3,k=3,m=9,B所有元素为0,元素x,y,z分别经过3个哈希函数映射到3个slot上,每一个元素经过一个独立的哈希函数生成指纹f(x)=11010,f(y)=10000,f(z)=01110,

我们可以看到slot7被元素z独享,所以slot7能够唯一标识z,将slot7打上标记z,并去除元素z的映射

此时slot5可以唯一标识元素y,将slot5打上标记y,并去除元素y的映射

现在只剩下最后一个元素x,f(x)可以放在slot1、slot3、slot6任一位置,这里选择slot1,slot3和slot6置为的5-bit 0,将f(x) xor slot2 xor slot3的结果放在slot1中,11010^00000^00000=11010,并回填其它带有标记的slot,和前面操作一样y元素slot5=f(y) xor slot1 xor slot6=10000^11010^00000=01010,z元素slot7=f(z) xor slot2 xor slot5=01110^00000^01010=00100

最终得到了构建好的Xor Filter,测试的时候,待检测的元素w经过3个哈希函数得到对应的slot索引h1(w),h2(w),h3(w),以及经过另一个哈希函数得到指纹f(w),将指纹与B(h1(w)) xor B(h2(w)) xor B(h3(w))进行比较。如若相等,则表示元素w可能存在,否者一定不存在。

2.3 Ribbon Filter

Ribbon Filter是Peter C. Dillinger和Stefan Walzer在2021年提出的[3],Ribbon Filter主体是Xor Filter的实现,在其基础上构建可以高效运算的矩阵,从而利用矩阵本身的高效运算来解决Xor Filter构建过程中的重复操作,相比Bloom Filter,Ribbon Filter会消耗更多的CPU,Ribbon Filter的核心优势在于节省空间,所以会针对Xor Filter的二维数组的求解过程做计算优化,Ribbon Filter会将二维数组的求解过程转化成解线性方程组Ax=b,并应用了基于行列式的高斯消元法,线性代数中求解线程方程组时会用到行列式运算,高斯消元法就是在求解线程方程组的过程中,将一个行列式转化成上三角或者下三角矩阵。

相比Xor Filter, Ribbon Filter主要差异如下:

  • Ribbon Filter哈希映射到数组连续的一片索引,而Xor Filter仅有的3个哈希函数每个都随机映射;
  • Ribbon Filter构建过程使用高斯消元法,Xor Filter使用Peeling算法;
  • Ribbon Filter二维bit数组使用列式存储,Xor Filter是行式存储;
  • Ribbon Filter相比Bloom Filter最高能节省30%的空间。

让我们看一下上节Xor Filter的元素w的查询测试过程,哈希映射用h(x)表示,

,即

= B[2] xor B[4] xor B[7] ,那是不是可以表示成

,其中

是元素w哈希映射的特征向量,第2,4,7位为1(索引从0算起),对应了

的值,Z是二维bit数组B的矩阵形式,

,同时注意

计算过程中加法运算要变成异或XOR运算。可以计算出query(w)=00100,

=

上节Xor Filter的构建过程可以用线性方程组表示成:

,二维bit数组B可以通过求解该方程组得到,方程组的系数矩阵为

,第1行对应了元素x哈希映射的特征向量,第2行y,第3行z。

除了引入矩阵运算,Ribbon Filter还对二维bit数组的存储结构进行了调整,在Xor Filter中每个slot的r-bit连续存储,且保证第i个slot中所有的bit都在第i+1个slot的r-bit前面,这种称为行式存储结构,而Ribbon Filter使用列式存储,保证每w个slot的第j个bit都在第j+1个bit前面,w是Ribbon Filter哈希映射到的连续索引的宽度,一般w>>r,如果使用行式存储,查询的时候需要从内存读取所有的w个r-bit,然后做异或计算得到结果并与指纹对比,现在使用列式存储,可以先读取第1个w-bit,做一下异或计算并将结果与指纹的第1个bit比较,如果不同则表示查询的元素不在集合内,直接返回False,否者继续读取接下来的w-bit并重复之前的过程。列式存储带来的好处有:

  • 查询过程不用读取所有的bit,减少查询时间;
  • 对空间更友好,访问w个连续内存空间变成了访问r个连续内存空间。一般w=64,r=7。

2.4 性能对比

依据Ribbon Filter论文的性能对比结论,我们提取出本文关心的Bloom,Xor,Ribbon三者的性能对比。这里的key用的是long数据类型,Construct包括添加key和求解方程。

Filterfalse positive ratespace overheadns/key,n=10^6,Constructns/key,n=10^6,Query
BlockedBloom1%52.0%1114
Xor1/2^8≈0.39%23.0%14815
Ribbon1/2^7≈0.78%10.1%8339

从表中可以看出:

  • Ribbon构建时间是BlockedBloom的7.5倍
  • Ribbon查询时间是BlockedBloom的2.8倍
  • Ribbon空间开销是BlockedBloom的72%((1+10.1%)/(1+52.0%)),节省了28%。

通过文章中的对比,我们发现Ribbon Filter虽然比Bloom Filter节省了28%的空间,但构建时间和查询时间都有了一些明显的上升。初看是一个时间换空间的做法,不过,论文中选用的Bloom Filter是BlockedBloom,这是2019年提出的一个基于Bloom Filter的优化版本[4],本身性能就已经比较好,而且测试的Filter hash function都是针对long值的,而Lindorm中的Bloom Filter是针对byte数组做hash的,性能表现可能不完全一致。因此,Ribbon Filter是否能在任何场景下都能Lindorm带来性能提升,需要我们把Ribbon Filter引入Lindorm中,在生产环境做一些测试。

3. 应用Ribbon Filter

3.1 核心逻辑的实现

我们参考论文中的Ribbon Filter使用Java进行了实现并集成到Lindorm中。论文中有一种空间开销更小的优化版本的Ribbon Filter,但是它不能保证构造成功,需要重试,这在Lindorm中是不能接受的,Lindorm中构建过滤器是不能失败的,否则会导致Flush或者Compaction失败。所以我们最后选用了宽度w=64的Homogeneous Ribbon Filter。

最终的实现有一些工程上的取舍,因此与论文还是存在一些差异:

  • 论文中实现的Ribbon Filter使用的key类型是long型,在Lindorm中每个key是一个byte数组;
  • 论文中实现的Ribbon Filter构建的时候直接提供一个key数组,但是在Lindorm中key是流式的一个个来,并且数量未知;
  • 论文中实现的Ribbon Filter构建提供key数组的大小n是已知的,可以通过公式

(错误率f已知)得到Ribbon Filter的空间大小,但是Lindorm中只提供空间大小bitSize和错误率f,key数量n未知,需要反向求出n;

  • 论文中实现的Ribbon Filter输出的是一个long型数组,但是在Lindorm中得是一个ByteBuffer才能统一存到文件系统中;
  • 论文中实现的Ribbon Filter查询过程可以使用类中全部中间变量,但是在Lindorm中查询函数是静态的,只有少部分meta信息和存有Ribbon Filter的数据块可以使用。

Ribbon Filter的构建:

Bloom Filter构建过程只需要添加元素即可,添加完了就构建完了,但是Ribbon Filter构建过程还包括求解方程阶段,这个阶段是最耗时的,这个阶段放在哪个地方在什么时间由谁调用来执行,会不会影响性能是一个大大的问题。目前是放在Ribbon Filter的写过程中执行,写之前会先求解方程,性能影响目前还没发现。

Ribbon Filter的查询:

Bloom只需要少量的meta信息然后按需加载需要的Bloom Block,就可以完成查询过程,meta信息有VERSION,byteSize,hashCount,hashType,keyCount。Ribbon不需要hashCount字段,其它都要,除此之外还需要numStarts(哈希映射到的区间上限),upperNumColumns(指纹位数的向上取整),upperStartBlock(指示floor(r)位的slot与ceil(r)的slot的分界),后续引入失败重试机制还得有哈希种子seed字段。

为了不改变meta信息的长度,只将hashCount变成了slotCount(slot的数量),都是int类型,numStarts = slotCount-63,upperNumColumns = (ribbonBitSize + slotCount - 1) / slotCount,upperStartBlock = upperNumColumns * (slotCount >> 6) - (ribbonBitSize >> 6),这样就完美了,从物理存储层是不太能看出Bloom meta block和Ribbon meta block的区别的,既没增字段也没减字段也没修改字段类型。

3.2 初步测试

本次benchmark对比的是在Lindorm中应用的Bloom Filter和Ribbon Filter。这里的key用的是byte数组类型,key length是byte数组大小;错误率都为1%,hash类型都是murmur,Construct包括添加key和求解方程。

1. Construct,构建filter,单位是ns/key, n=10^6,下同。

key lengthRibbon,ns/key, n=10^6Bloom,ns/key, n=10^6ratio (Ribbon:Bloom)
10109.926136.01280.82%
25143.178164.24787.17%
50196.083227.89886.04%
250334.312467.88471.45%
20001375.1652006.23568.54%

可以看到,在Lindorm中,随着Key长度的增长,构建Ribbon Filter的速度反而会更快

2. Query,查询

key lengthRibbon,ns/key, n=10^6Bloom,ns/key, n=10^6ratio (Ribbon:Bloom)
1020.82722.13594.09%
2538.28544.76485.53%
5051.73070.07573.82%
250147.951256.86357.60%
20001125.7602230.20050.48%

可以看到,在Lindorm中,随着Key长度的增长,查询Ribbon Filter的速度反而更快。

3. space load,空间负载跟key length无关

key lengthRibbon,bit/key, n=10^6Bloom,bit/key, n=10^6ratio (Ribbon:Bloom)
*7.2329.58575.45%

从初步测试的结果来看,似乎测试结论比论文中更好,无论查询速度,构建速度,Ribbon Filter都比Bloom Filter更优。我们分析,这是由于Lindorm中原来使用的BloomFilter是一个没有优化过的原始版本,而且Bloom Filter查询时需要多次执行hash函数,而hash bytes的消耗比论文中hash 数字的消耗要大的多,因此Ribbon Filter的查询性能并没有论文中说的那么差,反而随着key的长度变长,查询的性能要强于原有的BloomFilter实现并且差距越来越大。

构建Filter时的结论也类似,随着key长度的上升,RibbonFilter的构建速度更快,完全优于Bloom Filter。但在生产过程中,构建过滤器只占Lindorm生产LDFile全过程中的很小一部分,基本上不会对Lindorm文件的生成速度造成影响。在空间上,相同的错误率下,Ribbon Filter确实能比Bloom Filter节省25%的空间。

基于以上测试结论,我们觉得使用Ribbon Filter替代Bloom Filter,无论从哪个角度上来说,都是一个不错的选择。

3.3 生产测试

我们把Ribbon Filter集成在Lindorm宽表引擎中,进行了全链路的压测,压测机器的配置为4核8GB,使用ESSD存储,压测工具用的是ycsb

本次测试的是批量读的吞吐量对比测试和延迟对比测试,以及读取过程中的缓存命中率对比测试,以及major compaction性能对比测试。读取测试根据rowKey的字节数的不同分为四个场景:10bytes,25bytes,50bytes,300bytes。

测试表单节点分布,load10亿行数据,每行数据一个列族,共5列,每列value 20bytes,每行数据大概0.1kb,表大小100G左右,批量读一次20行。

批量读吞吐量对比

批量读平均延迟对比

读取过程中的缓存命中率对比

单节点major compaction性能对比(cpu打满)

Filter的meta信息对比

指标Bloom FilterRibbon Filter
Size(bytes)119930889043968
No of Keys99998339999833
Max Keys1000149910005000
Percentage filled100%100%
Number of chunks9269

生产的测试证实了我们在3.2节理论分析的结果。引入Ribbon Filter后,读的吞吐最高有了18%的提升。读RT有了最高15%的下降。吞吐的提升和RT的下降主要来源于使用Ribbon Filter后,过滤器空间的减少和内存命中率的提升。并且在不同的key大小下,Ribbon Filter均有好过Bloom Filter的表现。

在Compaction的对比测试中,大家也可以看到,使用Ribbon Filter与否对Compaction的速度基本没有影响。

4 总结

本文研究了一种新的过滤器Ribbon Filter。我们根据论文的思路在Lindorm中进行了实现。经过测试,我们发现Ribbon Filter能够节省25%的过滤器空间占用,从而在各种条件下提升Lindorm的读性能。Lindorm将在下一个版本中集成Ribbon Filter,带给用户极致地性能体验。

另外,为了保证Ribbon Filter构建不失败,我们选用了一种空间占用相对较多的实现,我们将在Ribbon Filter的基础上继续做了一些探索,保证构建不失败重试的前提下,进一步节省过滤器的空间。

参考文献

[1]Burton H. Bloom. 1970. Space/Time Trade-offs in Hash Coding with Allowable Errors. Commun. ACM 13, 7 (1970), 422–426.

[2]Thomas Mueller Graf and Daniel Lemire. 2020. Xor Filters: Faster and Smaller Than Bloom and Cuckoo Filters. ACM J. Exp. Algorithmics 25 (2020), 1–16. https://doi.org/10.1145/3376122

[3]Dillinger, Peter C. and Stefan Walzer. “Ribbon filter: practically smaller than Bloom and Xor.” *ArXiv* abs/2103.02515 (2021).

[4]Harald Lang, Thomas Neumann, Alfons Kemper, and Peter A. Boncz. 2019. Performance-Optimal Filtering: Bloom overtakes Cuckoo at High-Throughput. Proc. VLDB Endow. 12, 5 (2019), 502–515.

作者:箫苏 朝戈 正研

原文链接

本文为阿里云原创内容,未经允许不得转载。

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

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

相关文章

阿里云云原生一体化数仓 — 数据治理新能力解读

一、数据治理中心产品简介 阿里云DataWorks:一站式大数据开发与治理平台 架构大图 阿里云 DataWorks定位于一站式的大数据开发和治理平台,从下图可以看出,DataWorks 与 MaxCompute、Hologres 等大数据引擎紧密配合,在数据的 采、…

入门即享受!coolbpf 硬核提升 BPF 开发效率

编者按:BPF 技术还在如火如荼的发展着,本文先通过对 BPF 知识的介绍,带领大家入门 BPF,然后介绍 coolbpf 的远程编译(原名 LCC,LibbpfCompilerCollection),意为酷玩 BPF,…

拥抱开放,Serverless 时代的下一征程

Serverless 作为云计算的最佳实践和未来演进趋势,其全托管免运维的使用体验和按量付费的成本优势使得它在云原生时代备受推崇。Serverless 的使用场景也由事件驱动,数据处理等部分特定场景转向更为广泛通用化的 WEB,微服务,AI&…

云原生混部系统 Koordinator 架构详解

混部技术的介绍和发展 混部的概念可以从两个角度来理解,从节点维度来看,混部就是将多个容器部署在同一个节点上,这些容器内的应用既包括在线类型,也包括离线类型;从集群维度来看,混部是将多种应用在一个集…

全链路灰度在数据库上我们是怎么做的?

什么是全链路灰度? 微服务体系架构中,服务之间的依赖关系错综复杂,有时某个功能发版依赖多个服务同时升级上线。我们希望可以对这些服务的新版本同时进行小流量灰度验证,这就是微服务架构中特有的全链路灰度场景,通过…

InnoDB 之 UNDO LOG 介绍

undo log的组织形式 此部分是关于Undo log的组织形式的一个介绍;主要分为两部分来对undo log的组织形式进行介绍:文件结构和内存结构。在介绍这两部分时,先从局部出发,最后再给出各个部分的联系。 1. 文件结构 首先&#xff0c…

Spark 如何对源端数据做切分?

引言 典型的Spark作业读取位于OSS的Parquet外表时,源端的并发度(task/partition)如何确定?特别是在做TPCH测试时有一些疑问,如源端扫描文件的并发度是如何确定的?是否一个parquet文件对应一个partition&am…

数据库事务隔离发展历史

事务隔离是数据库系统设计中根本的组成部分,本文主要从标准层面来讨论隔离级别的发展历史,首先明确隔离级别划分的目标;之后概述其否定之否定的发展历程;进而引出 Adya给出的比较合理的隔离级别定义,最终总结隔离标准一…

为什么游戏行业喜欢用PolarDB

为什么游戏行业喜欢用PolarDB 游戏行业痛点 在我看来, 不同行业对数据库使用有巨大的差别. 比如游戏行业没有复杂的事务交易场景, 他有一个非常大的blob 字段用于存储角色的装备信息, 那么大Blob 字段的更新就会成为数据库的瓶颈, 比如在线教育行业需要有抢课的需求, 因此会有…

从业务开发中学习和理解架构设计

前言 在软件开发领域经常会接触到架构这个词汇,在我最初的印象中,架构是一个很高级的词汇。它似乎代表了复杂的工程结构、高层次的抽象设计、最新的开发语言特性等等。对于当时只专注于写业务逻辑的我来说,不免心生对架构的敬畏。工作中对架…

腾讯云联合中国联通打造下一代IDC数字化运营应用

近日,腾讯云联合中国联通智网创新中心打造的下一代IDC数字化运营应用,正式亮相2022中国联通合作伙伴大会。立足双方资源和经验优势,该数字化应用可实现对数据中心电力系统、制冷环境、安全防范等全方位智慧化运营,助力中国联通推进…

研发效能的思考总结

前言 在谈效能之前,我想先谈谈作为一个技术人或者技术TL,研发的核心价值是什么? 之前看了一篇文章,比较有意思,分享一下观念: T外包公司:最核心的竞争力不是技术,而是快速响应、资…

以“升舱”之名,谈谈云原生数据仓库 AnalyticDB 的核心技术

背景 说到升舱,我们首先想到的是飞机经济舱升级到商务舱、头等舱。阿里云企业级云原生数据仓库AnalyticDB(以下简称ADB)[1]在帮助以金融机构为主的行业数字化转型和传统数仓升级项目中,也引用了“升舱(仓)…

阿里云联合平行云推出云XR平台,支持沉浸式体验应用快速落地

近日,阿里云与平行云联合发布云XR平台,降低云端视觉计算应用的开发门槛,加速数字孪生、虚拟人、虚拟现实、沉浸式体验与虚拟仿真平台等XR应用落地,帮助互联网、新零售、社交、工业、交通、城市管理等行业探索创新业务形态。 阿里…

放弃笨重的 IDE,转而尝试 Emacs

【编者按】IDE对于开发者而言,重要性不言而喻,但随着功能愈发强大,它们对硬件的要求也日益提高,甚至越好用的 IDE 就越笨重。链接:https://renato.athaydes.com/posts/switching-from-heavyweight-ides-to-emacs.html声…

“穿越”到虚拟世界笑风生,网易瑶台沉浸式活动平台创新云端活动体验

2020年,第二届分布式人工智能国际会议(DAI 2020)因疫情的到来险些无法举办,南京大学人工智能学院的俞扬老师通过与网易伏羲团队的合作,最终在网易旗舰级武侠端游《逆水寒》中顺利举行了本次会议。300余位全球人工智能领…

云上解锁Web3.0 阿里云XR平台助力彼真科技呈现沉浸式演唱会

摘要:通过将沉浸式演唱会应用托管到云XR平台上,彼真科技也无需像传统应用一样做大量的终端适配工作,通过Web协议即可将虚拟演唱会《故障四方》的国风科幻世界呈现在不同的终端上。云XR平台完成了算力调度、渲染、推流、编码和用户管理等工作&…

这种精度高,消耗资源少的大模型稀疏训练方法被阿里云科学家找到了!

近日,阿里云机器学习PAI关于大模型稀疏训练的论文《Parameter-Efficient Sparsity for Large Language Models Fine-Tuning》被人工智能顶会IJCAI 2022接收。 论文提出了一种参数高效的稀疏训练算法PST,通过分析权重的重要性指标,得出了其拥有…

兼顾时尚与商务? ThinkPad Z 重新定义“商务本”

因为疫情等不确定因素,在过去三年中,混合办公模式已经成为职场的新常态。新一代工作族的商务办公笔记本不仅要随身携带完成日常工作,一些人还可能“身兼数职”,在工作之余也需要笔记本的配合。办公室里严谨、内敛商务本设计&#…

Go原生插件使用问题全解析

导言 本人在设计和落地基于Go原生插件机制的扩展开发产品时踩到了很多坑,由于这方面相关资料很少,因而借此机会做一个非常粗浅的总结,希望能对大家有所帮助。 本文只说问题和解决方案,不读代码。 一些背景知识 2.1 运行时 通…