树集成模型仍然是表格数据的首选,因为它们准确、训练成本相对较低且速度快。但是,如果您需要低于 10 毫秒的延迟或每秒数百万次的预测,那么在 CPU 上部署 Python 推理很快就会成为瓶颈。
2019 年,Forest Inference Library (FIL) 首次出现在 cuML 0.9 中,一直围绕着一件事:为梯度提升树和在 XGBoost、LightGBM、scikit-learn 或 NVIDIA cuML 中训练的随机森林提供快速推理。一般来说,如果您的模型可以转换为 Treelite,则可以使用 FIL。
FIL 已在 RAPIDS 25.04 中重新设计,新的亮点包括:
- 新的 C++ 实现,允许您在 GPU 或 CPU 上执行批量推理
- 用于调整推理模型的 optimize() 函数
- 全新高级推理 API (predict_per_tree, apply)
- GPU 吞吐量比 cuML 25.02 FIL 快高达 4 倍
在本博文中,您将了解 cuML 25.04 中 FIL 的新功能、性能和特性,并了解它比以前的 cuML 版本具有的优势。
快速入门示例 (XGBoost → FIL)
用户可以像往常一样在 XGBoost LightGBM 或 Scikit-learn 中训练模型,将其保存到磁盘中,然后使用 FIL 重新加载这些模型并将其应用于新数据。这可能发生在部署服务器中,也可能发生在与训练完全不同的硬件中。以下是易于使用的 Python API 的简单示例:
import xgboost as xgb
from cuml.fil import ForestInference
# Train your model as usual and save it
xgb_model = xgb.XGBClassifier()
xgb_model.fit(X_train, y_train)
xgb_model.save_model("xgb_model.ubj")
# Load into FIL and auto-tune for 10 k-row batches
fil_model = ForestInference.load("xgb_model.ubj")
# Now you can predict with FIL directly
preds = fil_model.predict(X_test)
probs = fil_model.predict_proba(X_test)
cuML 中 FIL 的新功能
自动优化
cuML 中的森林推理功能允许用户使用各种超参数微调性能。对于任何给定的模型和批量大小,很难预测最优值,因此通常需要根据经验确定这些值。新版本的 FIL 通过在任何给定批量大小下自动优化的内置方法显著简化了这一过程:
fil_model = ForestInference.load("xgb_model.ubj")
fil_model.optimize(batch_size=1_000_000)
result = fil_model.predict(data)
调用 .optimize
后,后续的预测调用将使用针对指定批量大小找到的最佳性能 hyperparameters。您还可以通过查看 .layout
和 .default_chunk_size
属性来检查所选择的 hyperparameters。
print(fil_model.layout)
print(fil_model.default_chunk_size)
新的预测 API
通常,我们只需输出森林模型的最终输出,无论是类预测还是所有树的组合数字输出。但是,有时,获取有关集成中单个树的更详细的信息会很有用。因此,我们引入了两种新的预测方法:.predict_per_tree
和 .apply
。
第一个是 .predict_per_tree
,分别给出每棵树的预测。这对于试验新的集成技术或分析集成如何达到整体预测非常有用。例如,用户可以根据树龄、out-of-bag AUC 甚至数据漂移分数对每棵树加权,然后对树进行平均投票,以做出更明智的最终决策,而无需重新训练。另一个示例是快速提供预测间隔,无需引导或不同的训练:
per_tree = fil_model.predict_per_tree(X)
mean = per_tree.mean(axis=1)
lower = cupy.percentile(per_tree, 10, axis=1)
upper = cupy.percentile(per_tree, 90, axis=1)
第二个参数 .apply
为给定输入提供每棵树的叶节点的节点 ID。这为森林模型开辟了新的用途,超越了简单的回归或分类。一个非常简单的应用是通过计算两行发送到同一叶的树的数量来测量它们的“相似性”:
leaf = fil_model.apply(X)
sim = (leaf[i] == leaf[j]).mean() # fraction of matching leaves
print(f"{sim:.0%} of trees agree on rows {i} & {j}")
GPU 和 CPU 支持
虽然 cuML 中的森林推理功能最初始于加速 GPU 上的森林推理,但用户希望在没有 NVIDIA GPU 的系统上开发森林推理应用。一个常见用例是在将模型部署到生产环境之前对小型数据子集进行本地测试。另一个有价值的用例是能够在流量较少时缩小到仅使用 CPU 的机器,并使用 GPU 进行扩展,以便在流量增加时从速度和成本节约中受益。
您可以在 CPU 模式下编译 FIL,并从 C++ 调用它。这允许您在不依赖任何 CUDA 的情况下使用它,同时仍然加载兼容 Treelite 的模型,并使用 OpenMP 在所有可用的 CPU 核心中分散推理。
对于 Python 用户,您可以尝试使用 cuML 25.04 中引入的新上下文管理器在 CPU 中执行 FIL。
from cuml.fil import ForestInference, get_fil_device_type, set_fil_device_type
with set_fil_device_type("cpu"):
fil_model = ForestInference.load("xgboost_model.ubj")
result = fil_model.predict(data)
未来版本还将提供可安装在 CPU-only 系统中的 Python 包。
FIL 如何加快速度
这个新版本通过降低从内存中提取数据的频率,加快了基于树的模型的速度。现在,树的每个决策点或节点都以所需的最小大小 (通常为 8 或 16 字节) 自动存储,并且节点以更智能的布局排列。大多数时候,处理器可以在单个快速读取中抓取下一个节点,而不是几个缓慢的节点。默认情况下,使用 depth_first
布局,该布局最适合更深的树 (深度 ≥ 4) 。如果您的树很浅,请尝试将 layered
用于较小的批量 (1–128 行) 或 breadth_first
用于较大的批量—but 记住,内置的 .optimize
函数可以为您测试它们。
此外,还引入了新的性能超参数 align_bytes
,以便对 depth_first
和 breadth_first
布局中的树进行对齐,使其从缓存行边界开始。这有时 (但并不总是) 会带来性能提升。CPU 上的 64 字节对齐可为大多数模型提供最佳性能。在 GPU 上,这种对齐很少能带来好处,但一些模型确实受益于 128 字节对齐。
性能
为了最全面地了解新 FIL 的性能特征,我们对其中每个变量进行了全面的扫描,如下表所示:
变量 | 价值 |
---|---|
最大树深度 | 2;4;8;16;32 |
树数量 | 16;128;1024;2048 |
特征计数 | 8;32;128;512 |
批量大小 | 1;16;128;1,024;1,048,576;16,777,216 |
A RandomForestRegressor
模型使用 10,000 行合成生成的数据,使用最大树深度、树数量和特征数量的每种组合进行训练。对于 cuML 25.04,我们使用了新的 .optimize
方法,并在之前的版本中使用了手动网格搜索。
然后,使用从与训练数据相同的分布中合成生成的输入批量来测试运行时性能。输入通过用于 GPU FIL 的 CuPy 数组和用于 CPU FIL 的 NumPy 数组提供。两个版本都进行了三次热身。然后,对每个批量大小进行五轮推理来测量性能,并在这些回合中使用最小运行时间。
GPU 结果使用了单个 NVIDIA H100 (80GB HBM3) ,CPU 结果使用了双路 Intel Xeon Platinum 8480CL 计算机。在所有这些场景中,cuML 25.04 在 75% 的情况下都优于上一个版本。下表显示了最佳、最差和中值的相对和绝对性能变化。如果相对提速低于 1,则表示性能回归。请注意,最差的绝对速度减慢是 62 毫秒,而最佳的绝对速度加快是 5 秒。
加速 ( cuML 25.04 与 25.02) | |
最低 | 0.73 倍 |
中值 | 1.16 倍 |
最大值 | 4.1 倍 |
虽然这些高层次的汇总统计数据可以大致了解新 FIL 的性能改进,但审查特定用例的性能也很有用。通常最值得关注的两个场景是批量大小 1 的性能和在任何批量大小下可获得的最大吞吐量。这些用例代表必须一次处理一个推理请求或最大限度地减少延迟至关重要的用例,以及可以批量推理以减少处理时间和费用的用例。

如图所示,在批量大小为 1 时,在 81% 的测试模型中,25.04 的性能优于之前的版本。对于包含许多深度树的模型而言,它的性能略逊一筹,但总体速度中值提高了 1.6x 倍。
下面的类似热图中显示了最大吞吐量性能。

在此情况下,在 76% 的模型中,cuML 25.04 的性能仍然优于上一个版本的原始 FIL,加速中值为 1.4 倍,在浅树情况下略有下降。
为全面了解性能,我们将 cuML 25.04 与 scikit-learn 的 RandomForest
性能进行了比较。scikit-learn 代码库的一大特色是其许多实现的简洁性。用户可以查看算法的实现,并快速了解其工作原理及其修改方式。
然而,对于 RandomForest
模型,这种方法并不总是能产生最高的推理性能。此次更新的一个重要目标是直接加速 scikit-learn 森林模型,以便用户在不增加 scikit-learn 代码库本身复杂性的情况下获得出色的推理性能。
在所有这些场景中,通过将 AMD EPYC 9654P 96 核 CPU 与单个 H100 (80GB HBM3) GPU 进行比较,FIL 的表现优于 scikit-learn 原生执行。与之前一样,我们在下表中总结了整体性能:
加速 (用于森林推理的全新 FIL 与原生 Sklearn 对比) | |
最低 | 13.9 倍 |
中值 | 147x |
最大值 | 882x |
批量大小 1 的加速如下所示:

从热图中可以计算出,批量大小 1 的中值加速为 239 倍。与 scikit-learn native 相比,我们通过以下方式展示了最大吞吐量性能:

立即开始在 NVIDIA cuML 中使用 FIL
cuML 中森林推理库的新重写提供了许多有用的新功能,并且相对于之前的版本,性能有了显著提升。新的自动优化功能可以更轻松地充分利用新的性能增强功能。
这使得 FIL 成为许多场景的理想选择:
- 面向用户的 API,其中每一毫秒都至关重要
- 大批量批处理作业 (广告点击评分、IoT analytics)
- 混合部署 – 相同的模型文件,在运行时选择 CPU 或 GPU
- 在本地进行原型设计并部署到 GPU 加速的生产服务器
- 降低成本 – 一个 GPU 可以取代 50 个或更多核心的 CPU。
立即下载 cuML 25.04 版本,试用 FIL 中包含的新森林推理功能。这些功能也将在 Triton Inference Server 的未来版本中提供。
即将发布的博客文章将分享此新实现的技术细节、进一步的基准测试,以及 FIL 与 NVIDIA Triton Inference Server 的集成。
如需详细了解 FIL (包括性能、API 文档、基准测试和更多内容) ,请参阅 cuML FIL 文档。如需了解有关加速数据科学的更多信息,请查看我们的 DLI 学习路径中的实战课程。