Skip to content

Commit 6265d9c

Browse files
authored
Promote experimental FIL to stable (#6464)
This PR promotes experimental FIL to the new stable FIL. This is purely a Python-level change. `cuml.fil.fil.ForestInference` now resolves to a thin wrapper around `cuml.experimental.fil.fil.ForestInference` with warnings about upcoming changes to the output shape of FIL predictions. Random forest estimators continue to use legacy FIL because of their usage of `TreeliteModel`, an obsolete implementation detail of legacy FIL. A future change should switch this to Treelite's native `treelite.Model` wrapper. The legacy FIL implementation has been moved to `cuml.legacy.fil.fil.ForestInference`. This can be removed in 25.06. The thin wrapper around `cuml.experimental.fil.fil.ForestInference` can also be removed in 25.06 once users have a deprecation cycle to adapt to new output shapes. This is marked as a breaking change because it removes the `shape_str` attribute from `ForestInference` objects. This attribute is not used anywhere in cuML and appears to have existed primarily for debugging. Resolve #6460. Authors: - William Hicks (https://github.com/wphicks) - Jim Crist-Harif (https://github.com/jcrist) Approvers: - Jim Crist-Harif (https://github.com/jcrist) - Simon Adorf (https://github.com/csadorf) - Dante Gama Dessavre (https://github.com/dantegd) URL: #6464
1 parent b38d8be commit 6265d9c

23 files changed

Lines changed: 316 additions & 218 deletions

docs/source/api.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ Forest Inferencing
399399

400400
.. autoclass:: cuml.ForestInference
401401
:members:
402+
:inherited-members:
402403

403404
Coordinate Descent
404405
------------------

python/cuml/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ add_subdirectory(cuml/decomposition)
144144
add_subdirectory(cuml/ensemble)
145145
add_subdirectory(cuml/explainer)
146146
add_subdirectory(cuml/experimental/fil)
147-
add_subdirectory(cuml/fil)
147+
add_subdirectory(cuml/legacy/fil)
148148
add_subdirectory(cuml/kernel_ridge)
149149
add_subdirectory(cuml/linear_model)
150150
add_subdirectory(cuml/manifold)

python/cuml/cuml/__init__.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
del libcuml
2626

2727
from cuml.internals.base import Base, UniversalBase
28-
from cuml.internals.available_devices import is_cuda_available
28+
from cuml.internals.available_devices import is_cuda_available, GPU_ENABLED
2929

3030
# GPU only packages
3131

@@ -44,8 +44,6 @@
4444

4545
from cuml.decomposition.incremental_pca import IncrementalPCA
4646

47-
from cuml.fil.fil import ForestInference
48-
4947
from cuml.ensemble.randomforestclassifier import RandomForestClassifier
5048
from cuml.ensemble.randomforestregressor import RandomForestRegressor
5149

@@ -54,7 +52,6 @@
5452
from cuml.explainer.tree_shap import TreeExplainer
5553

5654
import cuml.feature_extraction
57-
from cuml.fil import fil
5855

5956
from cuml.kernel_ridge.kernel_ridge import KernelRidge
6057

@@ -108,6 +105,11 @@
108105

109106
from cuml.cluster.hdbscan import HDBSCAN
110107

108+
# FIL is currently not built in cuml-cpu distributions, even though it can be
109+
# used in a CPU-only environment. Only import if the build supports it.
110+
if GPU_ENABLED:
111+
from cuml.fil import ForestInference
112+
from cuml.fil import fil
111113
from cuml.decomposition.pca import PCA
112114
from cuml.decomposition.tsvd import TruncatedSVD
113115

@@ -141,6 +143,7 @@ def __getattr__(name):
141143
# Modules
142144
"common",
143145
"feature_extraction",
146+
"fil",
144147
"metrics",
145148
"multiclass",
146149
"naive_bayes",

python/cuml/cuml/dask/ensemble/base.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright (c) 2021-2023, NVIDIA CORPORATION.
1+
# Copyright (c) 2021-2025, NVIDIA CORPORATION.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -13,7 +13,7 @@
1313
# limitations under the License.
1414
#
1515

16-
from cuml.fil.fil import TreeliteModel
16+
from cuml.legacy.fil.fil import TreeliteModel
1717
from cuml.dask.common.utils import get_client, wait_and_raise_from_futures
1818
from cuml.dask.common.input_utils import DistributedDataHandler, concatenate
1919
from dask.distributed import Future

python/cuml/cuml/ensemble/randomforest_common.pyx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ import typing
2626

2727
from cuml.internals.safe_imports import cpu_only_import
2828
np = cpu_only_import('numpy')
29-
from cuml import ForestInference
30-
from cuml.fil.fil import TreeliteModel
29+
from cuml.legacy.fil.fil import ForestInference
30+
from cuml.legacy.fil.fil import TreeliteModel
3131
from pylibraft.common.handle import Handle
3232
from cuml.internals.base import UniversalBase
3333
from cuml.internals.array import CumlArray
@@ -453,8 +453,10 @@ class BaseRandomForestModel(UniversalBase):
453453
_check_fil_parameter_validity(depth=self.max_depth,
454454
fil_sparse_format=fil_sparse_format,
455455
algo=algo)
456-
fil_model = ForestInference(handle=self.handle, verbose=self.verbose,
457-
output_type=self.output_type)
456+
with warnings.catch_warnings():
457+
warnings.simplefilter('ignore', FutureWarning)
458+
fil_model = ForestInference(handle=self.handle, verbose=self.verbose,
459+
output_type=self.output_type)
458460
tl_to_fil_model = \
459461
fil_model.load_using_treelite_handle(treelite_handle,
460462
output_class=output_class,
@@ -555,8 +557,10 @@ def _obtain_fil_model(treelite_handle, depth,
555557
fil_sparse_format=fil_sparse_format,
556558
algo=algo)
557559

558-
# Use output_type="input" to prevent an error
559-
fil_model = ForestInference(output_type="input")
560+
with warnings.catch_warnings():
561+
warnings.simplefilter('ignore', FutureWarning)
562+
# Use output_type="input" to prevent an error
563+
fil_model = ForestInference(output_type="input")
560564

561565
tl_to_fil_model = \
562566
fil_model.load_using_treelite_handle(treelite_handle,

python/cuml/cuml/ensemble/randomforest_shared.pxd

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2019-2023, NVIDIA CORPORATION.
2+
# Copyright (c) 2019-2025, NVIDIA CORPORATION.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.
@@ -26,7 +26,6 @@ from libcpp.vector cimport vector
2626
from libcpp.string cimport string
2727

2828
from pylibraft.common.handle import Handle
29-
from cuml import ForestInference
3029
from cuml.internals.base import Base
3130
from pylibraft.common.handle cimport handle_t
3231
cimport cuml.common.cuda

python/cuml/cuml/ensemble/randomforestclassifier.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ from cuml.ensemble.randomforest_common import BaseRandomForestModel
4848
from cuml.ensemble.randomforest_common import _obtain_fil_model
4949
from cuml.ensemble.randomforest_shared cimport *
5050

51-
from cuml.fil.fil import TreeliteModel
51+
from cuml.legacy.fil.fil import TreeliteModel
5252

5353
from libcpp cimport bool
5454
from libc.stdint cimport uintptr_t, uint64_t

python/cuml/cuml/ensemble/randomforestregressor.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ from cuml.ensemble.randomforest_common import BaseRandomForestModel
4747
from cuml.ensemble.randomforest_common import _obtain_fil_model
4848
from cuml.ensemble.randomforest_shared cimport *
4949

50-
from cuml.fil.fil import TreeliteModel
50+
from cuml.legacy.fil.fil import TreeliteModel
5151

5252
from libcpp cimport bool
5353
from libc.stdint cimport uintptr_t, uint64_t
Lines changed: 1 addition & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -1,122 +1,3 @@
11
# Experimental FIL - RAPIDS Forest Inference Library
22

3-
This experimental feature offers a new implementation of cuML's existing
4-
Forest Inference Library. The primary advantages of this new
5-
implementation are:
6-
7-
1. Models can now be evaluated on CPU in addition to GPU.
8-
2. Faster GPU execution on some models and hardware.
9-
3. Support for a wider range of Treelite's available model parameters.
10-
11-
In addition, there are a few limitations of this implementation,
12-
including:
13-
14-
1. Models with shallow trees (depth 2-4) typically execute slower than with
15-
existing FIL.
16-
2. This implementation has not been as exhaustively tested as the existing
17-
FIL.
18-
19-
If you need to absolutely maximize runtime performance, it is
20-
recommended that you test both the new and existing FIL implementations with
21-
realistic batch sizes on your target hardware to determine which is optimal
22-
for your specific model. Generally, however performance should be quite
23-
comparable for both implementations.
24-
25-
**NOTE:** Because this implementation is relatively recent, it is recommended
26-
that for use cases where stability is paramount, the existing FIL
27-
implementation be used.
28-
29-
## Usage
30-
With one exception, experimental FIL should be fully compatible with the
31-
existing FIL API. Experimental FIL no longer allows a `threshold` to be
32-
specified at the time a model is loaded for binary classifiers. Instead, the
33-
threshold must be passed as a keyword argument to the `predict` method.
34-
35-
Besides this, all existing FIL calls should be compatible with experimental
36-
FIL. There are, however, several performance parameters which have been
37-
deprecated (will now emit a warning) and a few new ones which have been added.
38-
39-
The most basic usage remains the same:
40-
```python
41-
from cuml.experimental import ForestInference
42-
43-
fm = ForestInference.load(filename=model_path,
44-
output_class=True,
45-
model_type='xgboost')
46-
47-
X = ... load test samples as a numpy or cupy array ...
48-
49-
y_out = fm.predict(X)
50-
```
51-
52-
In order to optimize performance, however, we introduce a new optional
53-
parameter to the `predict` method called `chunk_size`:
54-
55-
```python
56-
y_out = fm.predict(X, chunk_size=4)
57-
```
58-
59-
The API docs cover `chunk_size` in more detail, but this parameter controls
60-
how many rows within a batch are simultaneously evaluated during a single
61-
iteration of FIL's inference algorithm. The optimal value for this
62-
parameter depends on both the model and available hardware, and it is
63-
difficult to predict _a priori_. In general, however, larger batches benefit
64-
from larger `chunk_size` values, and smaller batches benefit from smaller
65-
`chunk_size` values.
66-
67-
For GPU execution, `chunk_size` can be any power of 2 from 1 to 32. For CPU
68-
execution, `chunk_size` can be any power of 2, but there is generally no
69-
benefit in testing values over 512. On both CPU and GPU, there is never
70-
any benefit from a chunk size that exceeds the batch size. Tuning the
71-
chunk size can substantially improve performance, so it is often worthwhile
72-
to perform a search over chunk sizes with sample data when deploying a model
73-
with FIL.
74-
75-
### Loading Parameters
76-
In addition to the `chunk_size` parameter for the `predict` and
77-
`predict_proba` methods, FIL offers some parameters for optimizing
78-
performance when the model is loaded. This implementation also
79-
deprecates some existing parameters.
80-
81-
#### Deprecated `load` Parameters
82-
83-
- `threshold` (will raise a `DeprecationWarning` if used)
84-
- `algo` (ignored, but a warning will be logged)
85-
- `storage_type` (ignored, but a warning will be logged)
86-
- `blocks_per_sm` (ignored, but a warning will be logged)
87-
- `threads_per_tree` (ignored, but a warning will be logged)
88-
- `n_items` (ignored, but a warning will be logged)
89-
- `compute_shape_str` (ignored, but a warning will be logged)
90-
91-
#### New `load` Parameters
92-
- `layout`: Replaces the functionality of `algo` and specifies the in-memory
93-
layout of nodes in FIL forests. One of `'depth_first'` (default) or
94-
`'breadth_first'`. Except in cases where absolutely optimal
95-
performance is critical, the default should be acceptable.
96-
- `align_bytes`: If specified, trees will be padded such that their in-memory
97-
size is a multiple of this value. Theoretically, this can improve
98-
performance by guaranteeing that memory reads from trees begin on a cache
99-
line boundary. Empirically, little benefit has been observed for this
100-
parameter, and it may be deprecated before this version of FIL moves out of
101-
experimental status.
102-
103-
#### Optimizing `load` parameters
104-
While these two new parameters have been provided for cases in which it is
105-
necessary to eke out every possible performance gain for a model, in general
106-
the performance benefit will be tiny relative to the benefit of
107-
optimizing `chunk_size` for predict calls.
108-
109-
## Future Development
110-
Once experimental FIL has been thoroughly tested and evaluated in real-world
111-
deployments, it will be moved out of experimental status and replace the
112-
existing FIL implementation. Before this happens, RAPIDS developers will
113-
also address the current underperformance of experimental FIL on shallow
114-
trees to ensure performance parity.
115-
116-
While this version of FIL remains in experimental status, feedback is very
117-
much welcome. Please consider [submitting an
118-
issue](https://github.com/rapidsai/cuml/issues/new/choose) if you notice
119-
any performance regression when transitioning from the current FIL, have
120-
thoughts on how to make the API more useful, or have features you
121-
would like to see in the new version of FIL before it transitions out of
122-
experimental.
3+
As of RAPIDS 25.04, experimental FIL has been promoted to stable. It is retained here temporarily to support users who have already migrated to experimental FIL, but it will be moved exclusively to `cuml.fil` in RAPIDS 25.06.

python/cuml/cuml/explainer/tree_shap.pyx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2021-2024, NVIDIA CORPORATION.
2+
# Copyright (c) 2021-2025, NVIDIA CORPORATION.
33
#
44
# Licensed under the Apache License, Version 2.0 (the "License");
55
# you may not use this file except in compliance with the License.
@@ -18,7 +18,7 @@ from cuml.common import input_to_cuml_array
1818
from cuml.internals.array import CumlArray
1919
from cuml.internals.import_utils import has_sklearn
2020
from cuml.internals.input_utils import determine_array_type
21-
from cuml.fil.fil import TreeliteModel
21+
from cuml.legacy.fil.fil import TreeliteModel
2222
from cuml.ensemble import RandomForestRegressor as curfr
2323
from cuml.ensemble import RandomForestClassifier as curfc
2424

0 commit comments

Comments
 (0)