尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Roaring Bitmap:海量整数集合存储与高效集合运算的工程实践
这次我们来看一个在互联网大厂和数据分析领域广泛使用的底层数据结构——Roaring Bitmap。它不是什么新潮的AI模型而是一个解决海量用户标签、实时人群圈选、多维分析等场景下如何高效存储和计算整数集合的“工程利器”。如果你处理过千万甚至亿级用户的标签系统或者被传统BitMap的内存占用所困扰那么这个项目值得你深入了解。简单来说Roaring Bitmap是一种压缩的位图索引。它的核心价值在于能用极小的内存开销对海量整数集合比如用户ID进行快速的交集、并集、差集运算。这直接决定了用户画像系统能否实时响应“25-35岁、一线城市、最近7天有购买行为的女性用户”这样的复杂查询。本文不会停留在概念层面而是聚焦于它的实现原理、性能优势、以及如何在你的技术栈中落地使用。我们将从以下几个关键点展开核心能力速览快速了解Roaring Bitmap能做什么、不能做什么。适用场景与边界明确它在用户标签系统、实时分析等场景中的具体位置。环境准备与依赖介绍主流语言Java/Go/Python等的库支持。基础操作与API通过代码示例演示创建、添加数据、集合运算等核心操作。性能实测与对比与传统BitMap、HashSet等进行内存和速度的直观对比。高级特性与调优探讨运行长度编码RLE、容器类型选择等进阶话题。集成到用户标签系统设计一个简化的标签存储与查询模型。常见问题与排查处理序列化、超大集合、JVM GC等问题。总结与最佳实践给出技术选型建议和避坑指南。无论你是后端开发、数据工程师还是架构师只要你的系统面临大规模集合运算的挑战这篇文章都能提供直接的参考方案。1. 核心能力速览在深入细节前我们先通过一个表格快速把握Roaring Bitmap的核心特性这有助于你判断它是否是你的“菜”。能力项说明核心问题高效存储和计算海量、稀疏的整数集合如用户ID。核心原理将32位整数空间0~2^32-1分桶高16位每个桶内根据数据密度自适应选择数组、位图或运行长度编码容器。内存占用极低且可预测。对于稀疏数据远小于传统位图对于稠密数据接近传统位图。通常比HashSet节省一个数量级以上的内存。查询性能极快。支持add,contains,and(交集),or(并集),andNot(差集),xor(对称差)等操作性能接近甚至优于传统位图。持久化支持序列化为二进制格式压缩率高便于落盘或网络传输。多语言支持Java、Go、C、C、Python、Rust等主流语言均有成熟实现如RoaringBitmap库。是否支持“50系显卡”/GPU不支持。这是一个纯CPU内存数据结构不涉及GPU计算。“显存”占用不适用。关注点是内存占用而非显存。“启动方式”库依赖引入。作为库集成到项目中无需独立服务“启动”。“接口API”提供丰富的编程API。通过调用类的方法进行操作而非HTTP接口。“批量任务”天生支持。所有集合运算都是批量进行的非常适合离线人群包计算、实时批量查询。适合场景用户标签系统、实时人群圈选、广告投放、数据分析中的维度组合查询、倒排索引、数据库查询优化。2. 适用场景与使用边界Roaring Bitmap不是万能的理解其适用场景和边界是正确使用的第一步。非常适合的场景用户画像与标签系统这是最经典的场景。每个标签如“性别男”、“城市北京”对应一个Roaring Bitmap存储具有该标签的所有用户ID。进行多标签组合查询AND时直接对多个Bitmap做交集运算速度极快。实时人群圈选在广告投放、活动推送中需要从亿级用户中实时筛选出符合多个条件的人群。利用Roaring Bitmap可以毫秒级返回结果。数据分析与OLAP在ClickHouse、Doris等OLAP数据库中常用Roaring Bitmap实现加速聚合查询如计算UV。倒排索引搜索引擎中每个词项对应的文档ID列表可以用Roaring Bitmap存储加速布尔查询。数据库索引某些数据库使用它作为二级索引加速等值查询和范围查询。不适用或需谨慎的场景非整数或离散性差的键Roaring Bitmap直接处理整数。如果键是字符串如用户名需要先通过字典映射为整数ID会引入额外复杂度。极高频的单点增删虽然支持add和remove但如果是每秒数百万次的随机单点更新其性能可能不如纯Hash结构。它更适合批量构建后用于查询或较低频率的更新。键空间非常小如果整数范围很小比如只有0-100直接使用传统BitMap或布尔数组可能更简单。需要存储关联数据Roaring Bitmap只存储“存在与否”不能存储键值对。如果需要存储用户ID - 标签值的映射需结合其他数据结构。合规与安全边界数据安全Roaring Bitmap本身是数据结构不涉及加解密。存储的用户ID等敏感信息需在应用层做好脱敏和权限控制。隐私保护用于用户分群时必须确保符合数据隐私法规如个人信息保护法仅对已授权、去标识化的数据进行分析。3. 环境准备与前置条件集成Roaring Bitmap非常简单主要工作是引入对应的库。这里以最常用的Java和Go版本为例。通用前提理解业务数据确认你的数据主体如用户ID是否可以映射为整数并评估数据的稀疏性ID是否连续。选择语言版本根据你的技术栈选择对应的成熟库。Java 环境 (以 Maven 项目为例):JDK版本JDK 8 及以上均可。依赖管理Maven或Gradle。核心依赖org.roaringbitmap:RoaringBitmap。这是最权威的Java实现。!-- Maven pom.xml 中的依赖 -- dependency groupIdorg.roaringbitmap/groupId artifactIdRoaringBitmap/artifactId version0.9.47/version !-- 请使用最新稳定版本 -- /dependencyGo 环境:Go版本Go 1.13。获取库使用go get。go get github.com/RoaringBitmap/roaringPython 环境:Python版本Python 3.6。安装库使用pip。有多种实现pyroaringbitmap是一个高性能的封装。pip install pyroaringbitmap4. 基础操作与API使用下面我们以Java为例展示Roaring Bitmap的基本使用方法。其他语言的API思想类似。4.1 创建与添加数据import org.roaringbitmap.RoaringBitmap; public class RoaringBitmapDemo { public static void main(String[] args) { // 1. 创建RoaringBitmap对象 RoaringBitmap rb1 new RoaringBitmap(); RoaringBitmap rb2 new RoaringBitmap(); // 2. 添加数据 - 支持单个添加和批量添加 rb1.add(1L); rb1.add(2L); rb1.add(3L); rb1.add(1000L); // 稀疏的大ID rb1.add(1000000L); // 非常稀疏的大ID // 批量添加 (高效) rb2.add(3L, 4L, 5L, 6L, 1000L); System.out.println(rb1: rb1); // 输出: {1,2,3,1000,1000000} System.out.println(rb2: rb2); // 输出: {3,4,5,6,1000} System.out.println(rb1 contains 1000? rb1.contains(1000)); // true System.out.println(rb1 cardinality (size): rb1.getCardinality()); // 5 } }4.2 核心集合运算集合运算是Roaring Bitmap的强项所有操作都返回新的Bitmap或修改原Bitmap且时间复杂度很低。// 接上文代码 // 3. 集合运算 RoaringBitmap andResult RoaringBitmap.and(rb1, rb2); // 交集 System.out.println(Intersection (rb1 AND rb2): andResult); // {3, 1000} RoaringBitmap orResult RoaringBitmap.or(rb1, rb2); // 并集 System.out.println(Union (rb1 OR rb2): orResult); // {1,2,3,4,5,6,1000,1000000} RoaringBitmap andNotResult RoaringBitmap.andNot(rb1, rb2); // 差集 (在rb1不在rb2) System.out.println(Difference (rb1 ANDNOT rb2): andNotResult); // {1,2,1000000} RoaringBitmap xorResult RoaringBitmap.xor(rb1, rb2); // 对称差集 (只在一个集合中) System.out.println(Symmetric Difference (rb1 XOR rb2): xorResult); // {1,2,4,5,6,1000000} // 4. 原地操作 (性能更好节省临时对象) RoaringBitmap rb1Clone rb1.clone(); rb1Clone.and(rb2); // rb1Clone 现在等于 rb1 rb2 System.out.println(rb1.and(rb2) in-place: rb1Clone);4.3 迭代与序列化// 5. 迭代所有元素 System.out.print(Iterating rb1: ); for (int i : rb1) { // 实现了Iterable接口 System.out.print(i ); } System.out.println(); // 6. 序列化与反序列化 (用于存储或传输) try { byte[] serialized rb1.serialize(); // 序列化为字节数组 System.out.println(Serialized size: serialized.length bytes); RoaringBitmap deserialized new RoaringBitmap(); deserialized.deserialize(ByteBuffer.wrap(serialized)); // 反序列化 System.out.println(Deserialized equals original? deserialized.equals(rb1)); // true // 也可以序列化到文件/输出流 // rb1.serialize(new DataOutputStream(new FileOutputStream(bitmap.bin))); } catch (IOException e) { e.printStackTrace(); }5. 性能实测与对比“纸上得来终觉浅”。我们设计一个简单的测试对比Roaring Bitmap、传统的java.util.BitSet和java.util.HashSetInteger在内存和性能上的差异。测试场景模拟存储100万个用户ID这些ID在0到1000万之间随机分布模拟稀疏数据。import org.roaringbitmap.RoaringBitmap; import java.util.BitSet; import java.util.HashSet; import java.util.Random; public class PerformanceBenchmark { public static void main(String[] args) { int numElements 1_000_000; int maxRange 10_000_000; Random rand new Random(42); // 固定种子保证可重复 // 生成随机ID int[] randomIds new int[numElements]; for (int i 0; i numElements; i) { randomIds[i] rand.nextInt(maxRange); } // 测试1: 内存占用 (估算) System.out.println( 内存占用估算 (存储 numElements 个随机ID) ); RoaringBitmap rb new RoaringBitmap(); BitSet bs new BitSet(maxRange); HashSetInteger hs new HashSet(numElements); long startTime, endTime; // 构建 startTime System.currentTimeMillis(); for (int id : randomIds) rb.add(id); endTime System.currentTimeMillis(); System.out.println(RoaringBitmap 构建时间: (endTime - startTime) ms); startTime System.currentTimeMillis(); for (int id : randomIds) bs.set(id); endTime System.currentTimeMillis(); System.out.println(BitSet 构建时间: (endTime - startTime) ms); startTime System.currentTimeMillis(); for (int id : randomIds) hs.add(id); endTime System.currentTimeMillis(); System.out.println(HashSet 构建时间: (endTime - startTime) ms); // 估算内存 (粗略使用序列化后大小作为代理指标) try { byte[] rbBytes rb.serialize(); System.out.println(RoaringBitmap 序列化大小: rbBytes.length / 1024 KB); // BitSet 序列化较复杂此处用 (maxRange/8) 估算其位数组内存 System.out.println(BitSet 位数组理论大小: (maxRange / 8) / 1024 KB); // HashSet 每个Integer对象Node开销很大远大于RoaringBitmap System.out.println(HashSet 内存开销通常 10 MB); } catch (Exception e) { e.printStackTrace(); } // 测试2: 查询性能 (交集) System.out.println(\n 集合运算性能 (与另一个相似Bitmap求交集) ); RoaringBitmap rb2 new RoaringBitmap(); for (int i 0; i numElements; i) { rb2.add(rand.nextInt(maxRange)); } startTime System.currentTimeMillis(); RoaringBitmap.and(rb, rb2); endTime System.currentTimeMillis(); System.out.println(RoaringBitmap 交集运算时间: (endTime - startTime) ms); // 对比BitSet BitSet bs2 new BitSet(maxRange); for (int id : randomIds) bs2.set(rand.nextInt(maxRange)); // 用新随机数填充 startTime System.currentTimeMillis(); BitSet resultBs (BitSet) bs.clone(); resultBs.and(bs2); endTime System.currentTimeMillis(); System.out.println(BitSet 交集运算时间: (endTime - startTime) ms); } }预期结果与分析内存Roaring Bitmap的序列化大小可能只有几百KB到几MB而BitSet的位数组固定需要约1.25MB1000万位HashSet的内存占用可能高达几十MB。构建时间三者相差不大Roaring Bitmap可能稍慢于BitSet因为需要维护容器结构。查询性能交集Roaring Bitmap与BitSet的性能在同一数量级甚至可能更快因为它只对非空容器进行计算。HashSet的交集操作retainAll会慢得多。结论对于稀疏的整数集合Roaring Bitmap在内存效率上具有压倒性优势同时保持了极高的集合运算性能。这正是它适合海量用户标签系统的根本原因。6. 高级特性与调优了解基本原理后可以关注一些高级特性来应对更复杂的场景。6.1 运行长度编码RLE容器当某个桶内的数据非常稠密或连续时例如存储了1-10000的所有整数Roaring Bitmap会自动使用运行长度编码RunContainer来存储格式为[start1, length1], [start2, length2]...。这比数组或位图更节省空间。你通常不需要手动干预算法会自动选择最优容器。6.2 容器类型与性能Roaring Bitmap内部有三种容器ArrayContainer存储排序后的short数组。适用于非常稀疏的数据元素数 4096。BitmapContainer存储一个长度为1024的bit位图因为桶内是低16位2^166553665536/641024个long。适用于稠密数据元素数 4096。RunContainer存储运行长度编码。适用于有长连续区间的数据。库会自动在它们之间转换以优化空间。在极端性能调优时可以关注这些容器的分布。6.3 批量操作与并行化批量添加始终优先使用add(long... values)或add(int... values)而不是循环调用add单次方法。并行聚合对于超大规模的Bitmap交集/并集可以考虑将Bitmap分片使用多线程并行计算各部分再合并结果。但Roaring Bitmap本身的运算已经非常快多数场景无需并行。6.4 不可变Bitmap如果Bitmap构建后不再修改可以将其转换为不可变Immutable形式以追求极致的读取性能和内存节省。某些实现如Go的roaring.FrozenBitmap专门为此优化。7. 集成到用户标签系统现在我们设计一个简化的用户标签存储与查询模型看看Roaring Bitmap如何落地。假设场景一个电商平台有1亿用户ID从1到100,000,000用户被打上各种标签如性别、年龄段、城市、消费等级、近期行为。存储设计标签维度表维护标签的元信息。CREATE TABLE tag_metadata ( tag_id INT PRIMARY KEY, tag_name VARCHAR(50), tag_category VARCHAR(50) ); -- 示例数据: (1, gender_male, demographic), (2, city_beijing, geo), (3, last_30d_purchaser, behavior)标签-用户索引使用Roaring Bitmap。可以为每个标签值存储一个Bitmap文件或在Redis等KV存储中存储序列化后的字节。方案A文件存储/tag_index/tag_1.bin,/tag_index/tag_2.bin...方案BRedis存储# Redis键设计: tag:{tag_id} SET tag:1 RoaringBitmap_serialized_bytes方案C数据库存储在HBase/MySQL中存储BLOB字段。查询流程多标签AND查询用户请求找出gender_maleANDcity_beijingANDlast_30d_purchaser的用户。根据标签名找到对应的tag_id1, 2, 3。从存储中加载这三个tag_id对应的Roaring Bitmaprb_gender,rb_city,rb_behavior。执行交集运算result RoaringBitmap.and(rb_gender, rb_city, rb_behavior)。得到的resultBitmap就是满足所有条件的用户ID集合。可以直接获取用户数result.getCardinality()。迭代获取具体用户ID列表。将结果Bitmap序列化后返回给前端或下游服务。代码示例模拟查询// 模拟从存储加载Bitmap (这里用内存对象模拟) RoaringBitmap maleUsers loadBitmapFromStorage(tag_1); // 假设有5000万男性用户 RoaringBitmap beijingUsers loadBitmapFromStorage(tag_2); // 假设有1000万北京用户 RoaringBitmap recentBuyers loadBitmapFromStorage(tag_3); // 假设有2000万近期购买用户 long start System.currentTimeMillis(); // 核心查询三步交集 RoaringBitmap targetUsers RoaringBitmap.and(maleUsers, beijingUsers, recentBuyers); long end System.currentTimeMillis(); System.out.println(多标签交集查询耗时: (end - start) ms); System.out.println(目标人群数量: targetUsers.getCardinality()); // 如果需要前100个用户ID int[] first100UserIds new int[100]; int pos 0; for (int userId : targetUsers) { first100UserIds[pos] userId; if (pos 100) break; }这个模型可以轻松扩展到OR并集、NOT非等更复杂的组合查询性能依然有保障。8. 常见问题与排查方法在实际使用中你可能会遇到以下问题问题现象可能原因排查方式解决方案内存占用比预期高1. 数据并非稀疏而是非常稠密。2. 存在大量小的、未压缩的ArrayContainer。3. JVM中Bitmap对象本身的开销。1. 使用rb.runOptimize()尝试压缩。2. 使用库提供的工具如RoaringBitmap.getSizeInBytes()精确测量。3. 分析容器类型分布。1. 对于稠密数据Roaring Bitmap接近BitSet这是正常的。2. 考虑是否真的需要存储全量数据能否分片3. 确保使用-XX:UseCompressedOops减少JVM对象头开销。集合运算速度慢1. 参与运算的Bitmap非常大且复杂。2. 在循环中频繁创建中间Bitmap对象。3. 硬件限制CPU缓存未命中。1. 检查运算的Bitmap基数元素个数。2. 审查代码避免不必要的对象创建多用原地操作(and,or)。3. 进行性能剖析。1. 对于超大规模运算评估是否可分批或使用近似算法。2.使用原地操作rb1.and(rb2)代替RoaringBitmap.and(rb1, rb2)。3. 考虑升级硬件或使用更高效的服务器。序列化/反序列化失败或慢1. 序列化格式不兼容不同版本库。2. Bitmap太大序列化后的字节数组导致GC压力。3. 反序列化时字节数据损坏。1. 确认生产与消费端使用的库版本一致。2. 监控JVM GC日志。3. 校验序列化前后的Bitmap是否相等。1. 统一依赖版本。2. 对于超大Bitmap考虑分片存储或使用serialize(DataOutput)流式写入文件避免大字节数组。3. 确保网络传输或存储过程无误。GC垃圾回收压力大1. 生成了大量临时的RoaringBitmap对象如在循环内。2. 序列化产生的大字节数组。1. 使用JVM分析工具如VisualVM, JProfiler观察对象分配。2. 检查代码热点。1.重用Bitmap对象在循环外创建用clear()或and/or原地操作复用。2. 使用对象池需谨慎可能增加复杂度。3. 调整JVM堆大小和GC策略。查询结果不正确1. 用于运算的Bitmap数据源有误未正确更新。2. 整数ID映射逻辑出错如字符串到ID的映射重复。3. 交集、并集逻辑用错。1. 对源Bitmap进行基数检查和抽样验证。2. 检查ID映射服务的逻辑。3. 编写单元测试验证基本集合运算。1. 建立数据校验机制定期对比源数据和Bitmap的基数。2.ID映射服务必须保证唯一性和稳定性。3. 核心查询逻辑必须有完整的单元测试覆盖。不支持64位整数业务ID范围超过32位约42亿。确认用户ID或其他键是否超过Integer.MAX_VALUE。1. 使用Roaring64NavigableMapJava库提供。2. 或将64位ID拆分到多个32位的Roaring Bitmap中如高32位和低32位分两个维度存储。9. 最佳实践与使用建议根据前面的分析总结出以下最佳实践帮助你用好Roaring Bitmap先评估后选用不是所有整数集合都适合。先分析数据基数、稀疏性、更新频率和查询模式。保证ID映射的稳定性如果原始键是字符串必须有一个稳定且唯一的ID生成与映射服务。ID一旦分配不应再改变。批量构建增量更新尽量在离线任务中批量构建Bitmap。对于实时更新可以采用“增量Bitmap”“全量Bitmap”定期合并的策略避免高频单点更新影响主Bitmap性能。善用序列化持久化将构建好的Bitmap序列化后存储到文件或KV数据库如Redis。下次直接反序列化加载避免重复构建。监控内存与性能在生产环境监控Roaring Bitmap的内存占用序列化大小和关键查询的耗时。设置告警阈值。为查询优化热标签常驻内存将最常查询的标签对应的Bitmap缓存在应用内存中。预计算交集对于固定且频繁查询的组合标签如“VIP用户”“北京”可以提前计算好交集生成一个新的Bitmap存储起来。使用不可变Bitmap如果Bitmap只读尝试使用不可变版本提升性能。注意JVM配置在Java中使用时确保启用压缩指针(-XX:UseCompressedOops)并根据Bitmap总大小合理设置堆内存。进行容量规划估算一个Bitmap的大致内存占用基数 * 2~4字节对于稀疏数据是一个很粗略的估算。规划好机器内存避免OOM。合规与数据安全存储用户ID的Bitmap本身是去标识化的但结合映射表就能还原。必须确保映射表和数据访问有严格的权限控制符合数据安全法规。Roaring Bitmap是一个将复杂问题优雅简化的典范。它没有炫酷的界面但在无数互联网公司的后台默默地支撑着每秒数亿次的用户画像查询。当你下次设计需要处理海量集合运算的系统时不妨首先考虑它。从一个小型的测试开始对比一下内存和性能的提升你可能会收获意想不到的惊喜。建议将本文中的代码示例和排查清单收藏在需要时快速参考。
RELATED

相关推荐

CAD2026图库插件:智能管理设计资产,提升团队协作效率

CAD2026图库插件:智能管理设计资产,提升团队协作效率

如果你是一名CAD设计师,每天的工作流程是不是这样:在十几个甚至几十个分散的文件夹里,大海捞针般地寻找一个特定的图块、一个标准的标题栏,或者一个曾经用过的阀门符号?找到后,复制粘贴,再手动调…

📅 2026/9/9 23:48:54
第 01 篇 一条 SELECT 语句是怎么执行的

第 01 篇 一条 SELECT 语句是怎么执行的

开篇钩子 SELECT * FROM t_user WHERE id 1; 这条你写过一万次的 SQL,从敲下回车到看到结果,MySQL 内部走了 6 道关卡。说不出来,就说明你只会用、不懂它。很多人在面试中被问到"MySQL 的架构"时,只能答出"有存储…

📅 2026/8/21 20:13:17
Unity原生C#热更新方案HybridCLR:原理、实战与工程化指南

Unity原生C#热更新方案HybridCLR:原理、实战与工程化指南

1. 项目概述:为什么我们需要一个“终极”热更新方案?做Unity开发的朋友,尤其是负责线上项目维护的,对“热更新”这三个字绝对是又爱又恨。爱的是它能在不重新发布客户端的情况下修复Bug、更新内容,是维系产品生命线的核…

📅 2026/9/9 20:53:16
MORE NEWS

更多资讯

📰

AXI Memory Mapped IP核BAR配置全解析:从原理到性能优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Vivado launch_simulation失败的三级定位与修复

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

【多智能体】多智能体系统在固定时间内的最佳燃料预算分配附matlab代码

✅作者简介:热爱科研的Matlab仿真开发者,擅长毕业设计辅导、数学建模、数据处理、算法改进、程序设计科研仿真。🍎 往期回顾关注个人主页:完整代码获取 定制创新 论文复现私信🍊个人信条:做科研&#xff0c…

📰

深度学习 - 25 DDP

DDP 深度教程 1. DDP 到底解决什么问题 DDP(DistributedDataParallel)解决的核心问题非常直接: 让多个 GPU 分别计算不同数据上的梯度,然后把这些梯度同步起来,使所有 GPU 可以像在一个更大的 batch 上训练一样更新同一个模型。 假设现在有 4 张 GPU: GPU0 …

📰

电脑操作--VirtualBox共享剪切板

6.1 问题现象VirtualBox装了个linux虚拟机,不知道怎么把主机的内容复制粘贴进去(2026-9-27)6.2 解决方案点设置,点常规,点功能,开启共享剪切板补装图形组件并启动服务sudo apt update sudo apt install -y virtualbox-guest-x11启…

📰

Model Optimizer 端到端示例测试指南:从运行到编写 tests/examples 全覆盖

人工智能大模型模型优化模型量化模型压缩 【免费下载链接】Model-Optimizer A unified library of SOTA model optimization techniques like quantization, distillation, pruning, neural architecture search, speculative decoding, etc. It compresses deep learning mode…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬