1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// gpu_compat.h — the single place where the shim's CUDA spelling is
// reconciled with the GPU vendor actually being built for.
//
// WHY THIS EXISTS
//
// libtorch is built for exactly ONE GPU backend, and both backends claim
// c10::DeviceType::CUDA: ROCm masquerades as CUDA all the way up to the
// dispatcher, which is why user code keeps saying .cuda() on an AMD box.
// The vendor is therefore a BUILD-TIME property, fixed at one per process
// — libtorch_cuda.so and libtorch_hip.so cannot be loaded together, as
// they would both register kernels against the same dispatch key.
//
// So the rest of the shim keeps CUDA spelling unconditionally and this
// header does all the reconciling. The mapping falls into three tiers,
// and the split is worth knowing before touching any of it:
//
// 1. IDENTICAL — no aliases needed, only the include path differs.
// torch::cuda::{is_available,device_count,manual_seed_all} live in
// libtorch_cpu.so and dispatch through the CUDA hooks that the HIP
// build registers. ATen/hip/HIPGraph.h and ATen/hip/HIPEvent.h
// declare at::cuda::{CUDAGraph,CUDAEvent,graph_pool_handle,
// MempoolId_t} under those exact names, with hip types in their
// signatures. That is deliberate upstream, not an accident.
//
// 2. MECHANICAL — c10::cuda::* -> c10::hip::*, and the raw runtime
// cudaXxx -> hipXxx. Pure renames, 1:1.
//
// 3. SEMANTIC, and the one item to actually understand: STREAMS.
// In a HIP build a tensor's device type is kCUDA while the native
// stream object lives on DeviceType::HIP. c10::hip::HIPStream is
// therefore NOT interchangeable with what a tensor hands you:
// passing one where a CUDA-typed stream is expected is a device-type
// mismatch, not a naming inconvenience. HIPStreamMasqueradingAsCUDA
// holds a HIPStream but reports device_type() == CUDA, coercing
// unsafely in both directions. Every stream alias below goes through
// it, and ATen/hip/HIPEvent.h is itself written against that same
// type, so events, streams and record_stream all line up.
//
// NOT handled here: the NCCL/RCCL header split, which stays at its own
// include site next to the collectives that need it.
// The torch library that registers the GPU backend's ATen kernels. It has
// to be force-loaded at process start; see the long note at the dlopen
// site in ops_nn.cpp for why `--as-needed` makes that load-bearing.
// ---------------------------------------------------------------- ROCm
// Tier 2: c10::cuda::* -> c10::hip::*.
//
// The HIP build ships c10/cuda/*.h as dead weight (they are the unbuilt
// CUDA headers, and their generated cuda_cmake_macros.h is absent), and
// there is no libc10_cuda.so to link against — libc10_hip.so exports
// c10::hip::* only. So c10::cuda does not exist here and we define it.
namespace c10 // namespace c10
// Tier 3: streams, via the masquerading wrapper. See the note above —
// the wrapper is what keeps a HIP stream usable wherever the dispatcher
// has already decided the device is kCUDA.
//
// at::cuda already exists at this point (HIPGraph.h and HIPEvent.h
// declare into it); these names are additions to it, not a redefinition.
namespace at // namespace at
// Tier 2 continued: the raw runtime API. Every name below was verified
// present 1:1 in ROCm 7.0's hip/hip_runtime_api.h. Function aliases are
// pointers rather than wrappers so the signature is exact by
// construction and cannot drift from the hip declaration.
using cudaError_t = hipError_t;
using cudaStream_t = hipStream_t;
using cudaDeviceProp = hipDeviceProp_t;
using cudaGraph_t = hipGraph_t;
using cudaStreamCaptureStatus = hipStreamCaptureStatus;
using cudaStreamCaptureMode = hipStreamCaptureMode;
constexpr auto cudaSuccess = hipSuccess;
constexpr auto cudaStreamCaptureStatusActive = hipStreamCaptureStatusActive;
constexpr auto cudaEventDisableTiming = hipEventDisableTiming;
constexpr auto cudaEventDefault = hipEventDefault;
constexpr auto cudaDeviceSynchronize = hipDeviceSynchronize;
constexpr auto cudaGetErrorString = hipGetErrorString;
constexpr auto cudaGraphDestroy = hipGraphDestroy;
constexpr auto cudaMemGetInfo = hipMemGetInfo;
constexpr auto cudaSetDevice = hipSetDevice;
constexpr auto cudaStreamEndCapture = hipStreamEndCapture;
constexpr auto cudaStreamIsCapturing = hipStreamIsCapturing;
// ROCm 6+ versions this symbol: hipGetDeviceProperties is a macro onto
// hipGetDevicePropertiesR0600, and hipDeviceProp_t onto the matching
// struct, so the two stay consistent through the alias above.
constexpr auto cudaGetDeviceProperties = hipGetDeviceProperties;
// ---------------------------------------------------------------- CUDA
// __HIP_PLATFORM_AMD__
// FLODL_BUILD_GPU