Marcus DuPont, author of SIMBI
Spitzer & FFPS Fellow, Princeton University
Heterogeneous-compute Interface for Portability (HIP) is a C++ runtime API and kernel language that allows developers to create portable applications for AMD and NVIDIA GPUs from a single codebase.
It is part of a larger initiative to ease the transition to GPU computing via a large software distro called the Radeon Open Compute Platform, or ROCm.
cuda functions with
hip, and most simple programs will still work.)
cudaMalloc, cudaMemset, cudaMemcpy)| Acronym | Meaning |
|---|---|
| HIP (by AMD) | Heterogeneous-compute Interface for Portability |
| CUDA (by Nvidia) | Compute Unified Device Architecture |
| Aspect | CUDA | HIP |
|---|---|---|
| Memory Allocation | cudaMalloc |
hipMalloc |
| Memory Deallocation | cudaFree |
hipFree |
| Memory Copy | cudaMemcpy |
hipMemcpy |
| Memory Set | cudaMemset |
hipMemset |
| Kernel Launch | kernel<< |
kernel<< |
| Device Synchronization | cudaDeviceSynchronize |
hipDeviceSynchronize |
| Get Last Error | cudaGetLastError |
hipGetLastError |
| Device Reset | cudaDeviceReset |
hipDeviceReset |
| Aspect | Host Code | Device Code |
|---|---|---|
| Execution Location | Runs on the CPU | Runs on the GPU |
| Function Declaration | Standard C++ functions | Declared with __global__ or __device__ qualifiers |
| Memory Allocation | Standard C++ memory allocation (e.g., malloc, new) |
HIP memory allocation functions (e.g., hipMalloc, hipFree) |
| Memory Access | Direct access to CPU memory | Access to GPU memory, requires explicit data transfer between host and device |
| Data Transfer | Not required | Explicit data transfer using functions like hipMemcpy |
| Parallelism | Typically sequential or multi-threaded using CPU threads | Massively parallel using GPU threads |
| Function Call | Standard function call | Kernel launch syntax (e.g., kernel<<) |
On AMD devices, the concept similar to CUDA's "warp" is called a "wavefront." A wavefront consists of 64 threads, whereas a warp in CUDA consists of 32 threads. This difference in the number of threads per execution unit is one of the key distinctions between AMD and NVIDIA architectures.
Here are some key differences between warps in CUDA and wavefronts in HIP:
Understanding these differences is crucial for optimizing performance on AMD and NVIDIA GPUs, as the size of warps and wavefronts can impact how you structure your parallel algorithms and manage thread divergence.
To install HIP, you need to install the ROCm software stack, which includes the HIP runtime and compiler. The ROCm software stack is available for Linux operating systems and supports a wide range of AMD GPUs.
To install ROCm, follow these steps:
Once HIP is installed, check that it works with the following command
hipcc --version
If that works, then compiling goes like:
hipcc -o hello_world hello_world.cpp
To check the platform, you can use the following code snippet:
hipconfig --platform
This will output the platform information, including the platform name, version, and other details. For example, it might output:
Platform: ROCm
Version: 4.0.0
Device: AMD Radeon RX 5700 XT
If the platform is autodetected incorrectly, it can be fixed by setting the correct environment variables. For example, if needing an Nvidia environment:
export HIP_PLATFORM=nvidia; export HIP_RUNTIME=cuda; export HIP_COMPILER=nvcc
HIP allows developers to write code that can run on both AMD and NVIDIA GPUs. This is achieved by providing a set of tools that allow developers to write code in a single-source manner, and then compile it for either platform.
For example, the following code snippet shows how to write a simple vector addition kernel in HIP:
__global__ void vector_add(int *a, int *b, int *c, int n) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n) {
c[i] = a[i] + b[i];
}
}
It's the same as CUDA (!)
HIP is designed to be very similar to CUDA, making it easier for developers to port CUDA applications to run on AMD hardware. Here are some key comparisons:
Since HIP code is C++ at its core, we can utilize key C++ constructs to make code a bit safer than C. For example, we can make custom vector classes utilize C++'s context switching to handle the memory management for us. The C++ context switching is called Resource Acquisition Is Initialization (RAII).
>
To reduce redundancy on writing CPU/GPU code, one can utilize macros and C++ lambda functions to achieve a single-implementation style program.
One could think even more modular and use code generation libraries. For example, the python-based cogapp does this. To generate
cpu or gpu code based on the platform, one could use the following code snippet within some, say, main.cpp.cog file:
The "some_cpu_code.cog" file might look like
and so forth...
Then generating the code with:
GPU_PLATFORM=amd cog -d -o main.cpp main.cpp.cog
HIP and ROCm provide a powerful platform for developing GPU-accelerated applications that can run on both AMD and NVIDIA hardware. By leveraging the similarities between HIP and CUDA, developers can more easily port their existing CUDA applications to run on AMD GPUs. Furthermore, lambda functions make generic programming on cpu/gpu architectures very streamlined. This is the bread and butter of third-party libraries like Kokkos.