Skip to content

Introduce layered shared utility libraries (common_utils + miopen_utils)#7253

Draft
BradPepersAMD wants to merge 12 commits intodevelopfrom
users/brpepers/miopen_shared_utils
Draft

Introduce layered shared utility libraries (common_utils + miopen_utils)#7253
BradPepersAMD wants to merge 12 commits intodevelopfrom
users/brpepers/miopen_shared_utils

Conversation

@BradPepersAMD
Copy link
Copy Markdown
Contributor

@BradPepersAMD BradPepersAMD commented May 9, 2026

Summary

  • Create two new shared utility libraries to eliminate circular dependencies between MIOpen driver, test, and library code
  • Move 13 pure C++ utility headers from src/include/miopen/ to common_utils/
  • Move 13 shared verification/test utility headers from test/ to miopen_utils/
  • Eliminate all cross-includes between driver/ and test/ in both directions
  • Remove 15 unnecessary includes where test files included driver headers without using them

Motivation

MIOpenDriver, tests, and the MIOpen library were tangled through circular includes:

  • 51 driver files included test headers
  • Test tensor_holder.hpp included driver/random.hpp (circular)
  • 18 test files included driver headers (14 unnecessarily)

This prevents building components independently and makes the dependency graph fragile.

Architecture

Note: Both common_utils and miopen_utils are internal build-only libraries.
They are not installed, not exported via find_package(MIOpen), and are not part of MIOpen's
public API. They exist solely to give the build system explicit, enforced edges between
driver/, test/, and src/. Consumers outside this repository should never depend on them.

This PR is Phase 1 of an incremental migration. Some layer boundaries listed below are not
yet fully enforced in code (e.g., common_utils/random.hpp still depends on miopen/env.hpp).
Known violations are listed as Phase 2 follow-up items. This PR is fully functionally equivalent
to the state before it — no runtime changes, no new build failures.

Layer 1: common_utils (no dependencies)

Pure C++ utilities. Depends only on STL/system headers. No MIOpen, no HIP, no GPU.

Layer 2: MIOpen Library (depends on: common_utils)

The MIOpen library itself. Uses common_utils internally. Exports the public miopen.h C API.

Layer 3: miopen_utils (depends on: common_utils, MIOpen public API)

Shared verification/test utilities. Uses common_utils and miopen.h. Cannot use MIOpen internal headers.

Layer 4: MIOpenDriver + Tests (depends on: common_utils, miopen_utils, MIOpen public API)

End consumers. Use all three lower layers via public interfaces. Never include MIOpen internals or each other.

common_utils (Layer 1) -- 13 headers

Pure C++ utilities with zero MIOpen dependencies:

  • ford.hpp, par_for.hpp -- parallel/sequential loop utilities
  • each_args.hpp, functional.hpp -- variadic template / function composition
  • float_equal.hpp -- ULP-based float comparison
  • bfloat16.hpp -- bfloat16 type (config dependency replaced with CMake define)
  • stringutils.hpp -- string utilities (MIOPEN_THROW replaced with std::runtime_error)
  • rank.hpp, returns.hpp, type_name.hpp, algorithm.hpp -- metaprogramming
  • reduce_common.hpp -- type conversion helpers
  • random.hpp -- PRNG (moved from driver/, breaks circular dep)

miopen_utils (Layer 3) -- 14 headers

Shared verification utilities used by both driver and tests. Depends on common_utils AND the MIOpen public API:

  • tensor_holder.hpp, verify.hpp -- core tensor container + numerical verification
  • cpu_conv.hpp, cpu_bias.hpp, cpu_layernorm.hpp -- CPU reference implementations
  • fusionHost.hpp, gemm.hpp, cpu_reduce_util.hpp, rnn_util.hpp -- more CPU refs
  • random.hpp, serialize.hpp, network_data.hpp -- tensor init + serialization
  • mloSoftmaxHost.hpp -- CPU softmax reference (moved from driver/)
  • gpu_mem.hpp -- GPUMem forwarding shim (Phase 2: extract from driver.hpp)

Backward compatibility

All original file locations retain thin forwarding headers, so existing MIOpen library and test code continues to work without changes.

Forwarding shims keep existing include paths working within the build tree.
No public headers or installed paths change.

Cross-include status

Boundary Before After
driver/ to test/ 54 includes 0
test/ to driver/ 18 includes 0
miopen_utils/ to test/ n/a 0
miopen_utils/ to driver/ n/a 1 (gpu_mem.hpp shim, Phase 2)
common_utils/ to miopen/ n/a 1 (random.hpp to env.hpp, Phase 2)

Phase 2 (follow-up)

  • Extract GPUMem class from driver.hpp into miopen_utils standalone header
  • Remove random.hpp dependency on miopen/env.hpp
  • Replace miopen::deref() and other internal symbol usage in driver
  • Refactor tensor_holder.hpp to use public MIOpen API instead of internal TensorDescriptor

Test plan

  • Build MIOpen library
  • Build MIOpenDriver
  • Build and run tests
  • Verify no circular includes between driver/ and test/
  • Verify common_utils/ has no miopen/ dependencies (except noted Phase 2 item)

BradPepersAMD and others added 5 commits May 9, 2026 07:08
Introduce a header-only common_utils library for pure C++ utilities
shared by MIOpen library, MIOpenDriver, and tests. This is the first
step toward a layered architecture that eliminates circular dependencies
between driver, test, and library code.

Move 9 utility headers from src/include/miopen/ to
common_utils/include/common_utils/:
- rank.hpp, returns.hpp, algorithm.hpp (zero-dependency)
- float_equal.hpp, each_args.hpp, type_name.hpp, par_for.hpp
- functional.hpp, ford.hpp (depend on other moved utilities)

Original locations retain thin forwarding headers for backward
compatibility. All internal cross-references within moved headers
updated to use common_utils/ paths.

CMake: common_utils added as INTERFACE library, linked by MIOpen,
MIOpenDriver, and test targets.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Continue populating the common_utils shared utility library:

- bfloat16.hpp: Removed miopen/config.h dependency, MIOPEN_USE_RNE_BFLOAT16
  now provided via CMake compile definition on the INTERFACE target
- stringutils.hpp: Replaced miopen/errors.hpp dependency with
  std::runtime_error, updated algorithm include to common_utils path
- reduce_common.hpp: Updated bfloat16 include to common_utils path
- random.hpp: Moved from driver/ to common_utils/ to break the circular
  dependency between driver/ and test/. Note: still depends on
  miopen/env.hpp (to be cleaned up in Phase 2)

Forwarding headers left at all original locations.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Move 12 headers from test/ to miopen_utils/include/miopen_utils/:
- tensor_holder.hpp, verify.hpp (used by 30+ driver files)
- cpu_conv.hpp, cpu_bias.hpp, cpu_layernorm.hpp (CPU reference)
- fusionHost.hpp, gemm.hpp, cpu_reduce_util.hpp, rnn_util.hpp
- random.hpp (test initializers)
- serialize.hpp, network_data.hpp (tensor_holder dependencies)

Include cleanup:
- Removed unused #include "test.hpp" from cpu_conv.hpp, cpu_bias.hpp
- Removed unused #include "get_handle.hpp" from fusionHost.hpp
- Updated all internal cross-references to use <miopen_utils/> and
  <common_utils/> paths

Updated 35 driver files to include from <miopen_utils/> instead of
<../test/>.

Forwarding headers left at original test/ locations for backward
compatibility with existing test code.

Result: driver/ no longer includes from test/, and miopen_utils/ no
longer includes from driver/ or test/.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Remove 15 unused #include directives where test files included driver
headers without using any symbols from them:
- 14 files included driver/tensor_driver.hpp unnecessarily
- 1 file included driver/conv_common.hpp unnecessarily

Remaining test→driver cross-references (3 files, all legitimate):
- softmax_find20.cpp → mloSoftmaxHost.hpp (CPU reference, move later)
- find_mode_trust_verify.cpp → driver.hpp (uses GPUMem)
- kernel_tuning_net.cpp → driver.hpp (uses GPUMem)

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Move mloSoftmaxHost.hpp (CPU softmax reference) to miopen_utils.
Create gpu_mem.hpp forwarding header in miopen_utils for GPUMem
(temporary Phase 1 shim; GPUMem extraction is Phase 2).

Update 3 test files to include through miopen_utils instead of
directly from driver/.

Result: zero cross-includes between driver/ and test/ in either
direction. The only remaining Phase 2 cleanup items are:
- miopen_utils/gpu_mem.hpp → driver/driver.hpp (extract GPUMem)
- common_utils/random.hpp → miopen/env.hpp (env var dependency)

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
BradPepersAMD and others added 6 commits May 9, 2026 10:19
The forwarding headers (e.g., src/include/miopen/rank.hpp) and their
targets (e.g., common_utils/include/common_utils/rank.hpp) used the
same include guard macro. This caused the target's content to be
skipped when included through the forwarding header, since the guard
was already defined by the forwarder.

Fix: Remove include guards from all forwarding headers entirely.
They contain no content of their own — just a single #include — so
the target file's own guard provides all necessary protection.

Affects 26 forwarding headers across src/include/miopen/, test/,
and driver/.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
The forwarding headers in src/include/miopen/ include <common_utils/...>
but the gtest build targets were not linking miopen_common_utils, so the
include directory was not on the search path. This caused build failures
for all gtest targets.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Same fix as the previous gtest commit: the forwarding headers in
src/include/miopen/ resolve to common_utils/ headers, so any target
that includes MIOpen internals needs miopen_common_utils on its
include path.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
The forwarding headers and removed driver/ cross-includes broke 8
test files in the unified miopen_gtest binary:

- test/fusionHost.hpp: add back get_handle.hpp include that the
  miopen_utils version correctly omits but test code depends on
- reduceextreme.hpp, reducecalculation.hpp: move miopen/miopen.h
  before kernel headers that static_assert on its macros
- layout_transpose.cpp: add float16 typedef lost when the
  driver/conv_common.hpp cross-include was removed

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Remove MIOpen:: namespace aliases (implies installed/exported targets) and
add EXCLUDE_FROM_ALL to both INTERFACE libraries. Strengthen CMake comments
to be explicit that these are not installed, not exported, and not part of
the public MIOpen API.

No functional or build behavior changes.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
The option was declared in two places (common_utils/ and src/), with the
src/ declaration being a silent no-op since common_utils/ runs first.

Move the single option() declaration to the top-level CMakeLists.txt,
which is the canonical location for all project-wide MIOpen build options.
Both common_utils/ and src/ now consume it from the CMake cache without
re-declaring it.

No functional or build behavior changes.

Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant