onnxruntime
6c959f7c - [Cuda Plugin] Refactor CUDA ops — Move more shared CPU/CUDA helper code from .cc to headers (Part 2) (#27628)

Commit
121 days ago
[Cuda Plugin] Refactor CUDA ops — Move more shared CPU/CUDA helper code from .cc to headers (Part 2) (#27628) ## Description This PR continues the refactoring effort started in PR #27617, moving additional CPU operator helper function implementations from `.cc` files into `.h` headers using the `#ifdef SHARED_PROVIDER` / `#else` inline pattern. This is a prerequisite for the **CUDA Plugin EP** work, where CUDA kernels are built into a standalone shared library (`libonnxruntime_providers_cuda_plugin.so`) that cannot link against the CPU provider's `.cc` object files. ### Why This Refactoring Is Needed The CUDA Plugin EP compiles CUDA operator kernels into a separate shared library that communicates with the ORT core through the ORT EP Plugin API. In this architecture, kernel source files **cannot** depend on framework-internal symbols that live in the CPU provider static library (`libonnxruntime_providers.a`). Many CUDA kernels inherit from CPU base classes and call shared helper/validation methods whose implementations currently live in CPU `.cc` files. In the in-tree CUDA EP build (`SHARED_PROVIDER` mode), these helpers are accessed through the `ProviderHostCPU` DLL-boundary virtual table bridge. However, the plugin EP does not use this bridge — it uses EP API adapters and force-included headers instead. To make these helpers available in the plugin build without duplicating code, this PR moves the implementations into headers as `inline` functions under `#ifndef SHARED_PROVIDER` guards. The `SHARED_PROVIDER` (in-tree) build path retains the existing declaration-only signatures that route through `ProviderHostCPU`. ### Refactoring Patterns Used 1. **Inline move**: Function body moved from `.cc` to `.h`, wrapped in `#ifndef SHARED_PROVIDER` with `inline` linkage. The `#ifdef SHARED_PROVIDER` path keeps the original declaration. 2. **Template-on-context**: Methods like `PrepareCompute`, `PrepareForCompute`, and `GetPresent` are templatized on `KernelContextType` so they work with both `OpKernelContext` (in-tree) and the plugin EP's adapter context. 3. **Template-on-info**: Constructors and initialization methods (e.g., `RoiAlignBase`, `CropBase`, `SpaceDepthBase`) are templatized on `KernelInfoType` with `info.template GetAttr<T>(...)` calls, making them compatible with both `OpKernelInfo` and the plugin's `OpKernelInfoAdapter`. 4. **Helper extraction**: Free helper functions (e.g., `CheckROIAlignValidInput`, `GetAxis`, `AdjustOutputSizeAsPolicy`) moved inline into headers. ## Summary of Changes ### Helper functions moved from `.cc` to `.h` (inline under `#ifndef SHARED_PROVIDER`) | Operator | Header File | Functions Moved | |----------|-------------|-----------------| | **AttentionBase** | `contrib_ops/cpu/bert/attention_base.h` | `AttentionBase::CheckInputs` (both overloads), `AttentionBase::CheckMask`, `AttentionBase::GetPresent` (templatized on `TOpKernelContext`) | | **LongformerAttentionBase** | `contrib_ops/cpu/bert/longformer_attention_base.h` | `LongformerAttentionBase::CheckInputs` | | **CumSum** | `cpu/math/cumsum.h` | `GetAxis` (free function) | | **RoiAlign** | `cpu/object_detection/roialign.h` | `CheckROIAlignValidInput` (free function), `RoiAlignBase` constructor templatized on `TKernelInfo` | | **Concat** | `cpu/tensor/concatbase.h` | `ConcatBase::PrepareForCompute` (templatized, delegates to `PrepareForComputeImpl`) | | **Gather** | `cpu/tensor/gatherbase.h` | `GatherBase::PrepareForCompute` (templatized, delegates to `PrepareForComputeImpl`) | | **Unsqueeze** | `cpu/tensor/unsqueeze.h` | `UnsqueezeBase::PrepareCompute` (templatized on `KernelContextType`) | | **Upsample** | `cpu/tensor/upsamplebase.h` | `UpsampleBase::AdjustOutputSizeAsPolicy`, `upsamplebase_helper::AdjustOutputSizeAsPolicy` (free helper) | ### Constructor templatization (for plugin EP adapter compatibility) | Class | Header File | Change | |-------|-------------|--------| | **CropBase** | `contrib_ops/cpu/crop.h` | Constructor templatized on `KernelInfoType`, `GetAttrsOrDefault` calls use `info.template` syntax | | **SpaceDepthBase** | `cpu/tensor/space_depth_ops.h` | Constructor templatized on `KernelInfoType`, `GetAttr` call uses `info.template` syntax | | **RoiAlignBase** | `cpu/object_detection/roialign.h` | Constructor templatized on `TKernelInfo`, all `GetAttr` calls use `info.template` syntax | ### CUDA-side updates | File | Change | |------|--------| | `cuda/tensor/upsample.cc` | Added explicit template instantiations for `Upsample<float>`, `Upsample<double>`, `Upsample<MLFloat16>`, `Upsample<int32_t>`, `Upsample<uint8_t>` (needed because `AdjustOutputSizeAsPolicy` implementation moved to header) | ### Files with code removed (moved to headers) | Source File | Lines Removed | Moved To | |-------------|---------------|----------| | `contrib_ops/cpu/bert/attention_base.cc` | ~333 | `attention_base.h` | | `contrib_ops/cpu/bert/longformer_attention_base.cc` | ~133 | `longformer_attention_base.h` | | `cpu/math/cumsum.cc` | ~23 | `cumsum.h` | | `cpu/object_detection/roialign.cc` | ~74 | `roialign.h` | | `cpu/tensor/concat.cc` | ~8 | `concatbase.h` | | `cpu/tensor/gather.cc` | ~4 | `gatherbase.h` | | `cpu/tensor/unsqueeze.cc` | ~51 | `unsqueeze.h` | | `cpu/tensor/upsample.cc` | ~44 | `upsamplebase.h` | ## Testing - Existing unit tests cover all affected operators (Attention, LongformerAttention, CumSum, RoiAlign, Concat, Gather, Unsqueeze, Upsample, Crop, SpaceToDepth/DepthToSpace). - No behavioral changes — all function logic is identical; only the location (header vs. source) and linkage (inline vs. external) changed. - The `SHARED_PROVIDER` code path (in-tree CUDA EP build) is unchanged — declarations remain and route through the existing `ProviderHostCPU` bridge. ## Motivation and Context This is part of the ongoing CUDA Plugin EP effort to build CUDA kernels as a standalone shared library that can be updated independently of the ORT core. The refactoring enables additional CUDA operators to compile in the plugin build by making their CPU-side validation and preparation helpers available as header-inline functions. This PR is a direct continuation of PR #27617 which applied the same pattern to Slice, Split, ScatterND, Tile, Pad, BiasGelu, EmbedLayerNorm, and NonMaxSuppression operators.
Author
Parents
Loading