Skip to content

[mt] GPU implementation of OHE vector leaf.#12276

Merged
trivialfis merged 4 commits into
dmlc:masterfrom
trivialfis:mt-cat-cuda
Jul 1, 2026
Merged

[mt] GPU implementation of OHE vector leaf.#12276
trivialfis merged 4 commits into
dmlc:masterfrom
trivialfis:mt-cat-cuda

Conversation

@trivialfis

Copy link
Copy Markdown
Member

No description provided.

@trivialfis
trivialfis requested a review from Copilot June 30, 2026 14:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the GPU hist multi-target (vector leaf) path to support categorical one-hot splits, aligning behavior with the CPU HistMultiEvaluator and adding targeted test coverage.

Changes:

  • Add categorical one-hot split support to the GPU multi-target split evaluation path (scan + gain evaluation) and apply categorical splits when expanding the tree.
  • Plumb feature type metadata to device evaluation kernels for categorical detection.
  • Add/extend GPU Python + C++ unit tests to cover multi-target categorical one-hot behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/python-gpu/test_gpu_updaters.py Adds a multi-target categorical OHE GPU test invocation.
tests/cpp/tree/gpu_hist/test_multi_evaluate_splits.cu Adds a focused C++ GPU unit test validating categorical one-hot split selection/weights.
src/tree/updater_gpu_hist.cuh Enables categorical split expansion for multi-target GPU hist (ExpandCategorical with one-hot bitfield).
src/tree/gpu_hist/multi_evaluate_splits.cu Implements categorical one-hot scan + evaluation paths for multi-target GPU split search.
src/tree/gpu_hist/evaluate_splits.cuh Adds WarpSum helper and threads feature type span into MultiEvaluateSplitSharedInputs.
src/tree/gpu_hist/evaluate_splits.cu Switches warp reductions/broadcast masks to the shared WarpSum/WarpFullMask helpers.
src/common/device_helpers.cuh Adds WarpFullMask() constant used by shuffle operations.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/tree/gpu_hist/multi_evaluate_splits.cu Outdated
Comment thread src/tree/gpu_hist/multi_evaluate_splits.cu Outdated
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
@trivialfis
trivialfis requested a review from RAMitchell July 1, 2026 07:32

@RAMitchell RAMitchell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, but from codex:

[P1] Scan buffer is under-sized for high-cardinality categorical features.
MakeSharedInputs passes param_.max_bin as n_bins_per_feat_tar, and EvaluateSplits() sizes scan_buffer_ as n_targets * Features() * n_bins_per_feat_tar * 2. But the new categorical scan writes using the global categorical bin_idx from feature_segments, e.g. region_others[bin_idx * n_targets + t]. Categorical cuts are not necessarily bounded by max_bin; existing tests explicitly cover n_categories = 32 with max_bin = 16 and expect categorical cut storage sized by categories, not max_bin.
Suggested fix: size the multi-target scan buffer by actual total bins per target, for example a host scalar derived from cuts_->TotalBins() / cut_values_.Size(), not Features() * max_bin. Add a regression test with multi_output_tree, categorical data, and n_categories > max_bin.
[P1] Non-OHE categorical features are silently evaluated as OHE.
The new multi-target categorical branches always run one-hot scan/evaluation and return. That diverges from existing CPU and single-target GPU behavior, which check UseOneHot(...) and otherwise use partition-based categorical splits. The added Python coverage only forces OHE for multi-target, and the partition test path is skipped when multi_target=True.
Suggested fix: either keep categorical vector-leaf GPU unsupported unless every categorical feature satisfies UseOneHot, or implement the partition path for multi-target. Add a test with multi_strategy="multi_output_tree" and max_cat_to_onehot=1 to verify the intended behavior.
Positive notes
The OHE missing-direction algebra itself looks consistent: one region stores “other categories” with missing-right, the other stores the matching bin with missing-left, and the final weight assignment uses dir to reconstruct left/right sums. The new C++ test validates the dense no-missing OHE case and expected vector weights.

@trivialfis

Copy link
Copy Markdown
Member Author
  1. Added a check for max bin
  2. There's no way to distinguish at the moment. The only fix is to implement the partition-based split.

@trivialfis
trivialfis merged commit fb4e8b5 into dmlc:master Jul 1, 2026
81 checks passed
@trivialfis
trivialfis deleted the mt-cat-cuda branch July 1, 2026 12:57
@trivialfis trivialfis mentioned this pull request Jul 9, 2026
48 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants