From 3a375a3d04846ad278ebb95312e8156aa641883a Mon Sep 17 00:00:00 2001 From: zz002 Date: Sat, 28 Feb 2026 12:47:05 -0600 Subject: [PATCH 1/2] Remove s_kernel_registry_vitisaiep.reset() in deinitialize_vitisai_ep() (#27295) Remove unnecessary s_kernel_registry_vitisaiep.reset() call in deinitialize_vitisai_ep() function. The kernel registry will be repopulated on next initialization, making this reset redundant. --- onnxruntime/core/providers/vitisai/imp/global_api.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/onnxruntime/core/providers/vitisai/imp/global_api.cc b/onnxruntime/core/providers/vitisai/imp/global_api.cc index ec529c2ad1fc2..0c1c930132da3 100644 --- a/onnxruntime/core/providers/vitisai/imp/global_api.cc +++ b/onnxruntime/core/providers/vitisai/imp/global_api.cc @@ -386,7 +386,6 @@ void deinitialize_vitisai_ep() { s_domains_vitisaiep.clear(); s_library_vitisaiep.Clear(); - s_kernel_registry_vitisaiep.reset(); } static void set_version_info(vaip_core::OrtApiForVaip& api) { From 5a5b2687e0091ca5add5d332d782a1647c0317f0 Mon Sep 17 00:00:00 2001 From: Adam Scarr Date: Mon, 2 Mar 2026 07:10:06 +1100 Subject: [PATCH 2/2] =?UTF-8?q?Fix=20O(n=C2=B2)=20model=20load=20time=20fo?= =?UTF-8?q?r=20TreeEnsemble=20with=20categorical=20feature=20chains=20(#27?= =?UTF-8?q?391)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Profiling shows that CheckIfSubtreesAreEqual is invoked recursively for many node pairs for LightGBM models with categorical features. A significant portion of this work consists of self-comparisons (left_id == right_id), leading to effectively O(n²) comparing trees to themselves during model loading. This change adds a fast-path for trivial equality, avoiding unnecessary recursive comparisons. Example results: - model with 7K BRANCH_EQ nodes: 527 ms → 47 ms (~11× faster) - model with 106K BRANCH_EQ nodes: 141 s → 80 ms (~1760× faster) ### Motivation and Context We have some LightGBM exported models that make heavy use of categorical features and exhibit extremely slow load times (minutes for a single 2.5mb model). Heres a diagram to illustrate the issue: image the 106K model has much longer "member of" chains, with chains that lead into more chains:
"trees" image
Interestingly we did also try using the new onnx.ml opset 5 node that has MEMBER, but it seems even slower as it recreates these branch EQ chains. --- onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h b/onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h index a136bf0d3b1f0..a4f75fa9a13ea 100644 --- a/onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h +++ b/onnxruntime/core/providers/cpu/ml/tree_ensemble_common.h @@ -384,6 +384,9 @@ bool TreeEnsembleCommon::CheckIfSubtreesAr gsl::span nodes_values_as_tensor, gsl::span node_values, gsl::span target_class_weights, gsl::span target_class_weights_as_tensor, const InlinedVector& node_tree_ids, InlinedVector> indices) { + if (left_id == right_id) { + return true; + } // Leaves have values set at 0 if (cmodes[left_id] != cmodes[right_id] || nodes_featureids[left_id] != nodes_featureids[right_id] || (!nodes_values_as_tensor.empty() && nodes_values_as_tensor[left_id] != nodes_values_as_tensor[right_id]) ||