Sync HIP documentation 2025-10-20 (#1258)

* Add examples to tools folder
* Correct P2P memory access section
* Sync poriting guide
* Add HIP Graph tutorial
* Add hint about using amdgpu-dkms for IPC API
* Add a few more env variables
This commit is contained in:
Istvan Kiss
2025-10-29 07:42:06 +01:00
committed by GitHub
szülő 8e98b80deb
commit 197f73dac9
89 fájl változott, egészen pontosan 10327 új sor hozzáadva és 3486 régi sor törölve
@@ -11,92 +11,10 @@ example and comparison table. For a complete list of mappings, visit :ref:`HIPIF
The following CUDA code example illustrates several CUDA API syntaxes.
.. code-block:: cpp
#include <iostream>
#include <vector>
#include <cuda_runtime.h>
__global__ void block_reduction(const float* input, float* output, int num_elements)
{
extern __shared__ float s_data[];
int tid = threadIdx.x;
int global_id = blockDim.x * blockIdx.x + tid;
if (global_id < num_elements)
{
s_data[tid] = input[global_id];
}
else
{
s_data[tid] = 0.0f;
}
__syncthreads();
for (int stride = blockDim.x / 2; stride > 0; stride >>= 1)
{
if (tid < stride)
{
s_data[tid] += s_data[tid + stride];
}
__syncthreads();
}
if (tid == 0)
{
output[blockIdx.x] = s_data[0];
}
}
int main()
{
int threads = 256;
const int num_elements = 50000;
std::vector<float> h_a(num_elements);
std::vector<float> h_b((num_elements + threads - 1) / threads);
for (int i = 0; i < num_elements; ++i)
{
h_a[i] = rand() / static_cast<float>(RAND_MAX);
}
float *d_a, *d_b;
cudaMalloc(&d_a, h_a.size() * sizeof(float));
cudaMalloc(&d_b, h_b.size() * sizeof(float));
cudaStream_t stream;
cudaStreamCreateWithFlags(&stream, cudaStreamNonBlocking);
cudaEvent_t start_event, stop_event;
cudaEventCreate(&start_event);
cudaEventCreate(&stop_event);
cudaMemcpyAsync(d_a, h_a.data(), h_a.size() * sizeof(float), cudaMemcpyHostToDevice, stream);
cudaEventRecord(start_event, stream);
int blocks = (num_elements + threads - 1) / threads;
block_reduction<<<blocks, threads, threads * sizeof(float), stream>>>(d_a, d_b, num_elements);
cudaMemcpyAsync(h_b.data(), d_b, h_b.size() * sizeof(float), cudaMemcpyDeviceToHost, stream);
cudaEventRecord(stop_event, stream);
cudaEventSynchronize(stop_event);
cudaEventElapsedTime(&milliseconds, start_event, stop_event);
std::cout << "Kernel execution time: " << milliseconds << " ms\n";
cudaFree(d_a);
cudaFree(d_b);
cudaEventDestroy(start_event);
cudaEventDestroy(stop_event);
cudaStreamDestroy(stream);
return 0;
}
.. literalinclude:: ../tools/example_codes/block_reduction.cu
:start-after: // [sphinx-start]
:end-before: // [sphinx-end]
:language: cpp
The following table maps CUDA API functions to corresponding HIP API functions, as demonstrated in the
preceding code examples.
@@ -337,117 +337,7 @@ The kernel function ``computeDFT`` shows various HIP complex math operations in
The example also demonstrates proper use of complex number handling on both host and device, including
memory allocation, transfer, and validation of results between CPU and GPU implementations.
.. code-block:: cpp
#include <hip/hip_runtime.h>
#include <hip/hip_complex.h>
#include <iostream>
#include <vector>
#include <cmath>
#define HIP_CHECK(expression) \
{ \
const hipError_t err = expression; \
if (err != hipSuccess) { \
std::cerr << "HIP error: " \
<< hipGetErrorString(err) \
<< " at " << __LINE__ << "\n"; \
exit(EXIT_FAILURE); \
} \
}
// Kernel to compute DFT
__global__ void computeDFT(const float* input,
hipFloatComplex* output,
const int N)
{
int k = blockIdx.x * blockDim.x + threadIdx.x;
if (k >= N) return;
hipFloatComplex sum = make_hipFloatComplex(0.0f, 0.0f);
for (int n = 0; n < N; n++) {
float angle = -2.0f * M_PI * k * n / N;
hipFloatComplex w = make_hipFloatComplex(cosf(angle), sinf(angle));
hipFloatComplex x = make_hipFloatComplex(input[n], 0.0f);
sum = hipCaddf(sum, hipCmulf(x, w));
}
output[k] = sum;
}
// CPU implementation of DFT for verification
std::vector<hipFloatComplex> cpuDFT(const std::vector<float>& input) {
const int N = input.size();
std::vector<hipFloatComplex> result(N);
for (int k = 0; k < N; k++) {
hipFloatComplex sum = make_hipFloatComplex(0.0f, 0.0f);
for (int n = 0; n < N; n++) {
float angle = -2.0f * M_PI * k * n / N;
hipFloatComplex w = make_hipFloatComplex(cosf(angle), sinf(angle));
hipFloatComplex x = make_hipFloatComplex(input[n], 0.0f);
sum = hipCaddf(sum, hipCmulf(x, w));
}
result[k] = sum;
}
return result;
}
int main() {
const int N = 256; // Signal length
const int blockSize = 256;
// Generate input signal: sum of two sine waves
std::vector<float> signal(N);
for (int i = 0; i < N; i++) {
float t = static_cast<float>(i) / N;
signal[i] = sinf(2.0f * M_PI * 10.0f * t) + // 10 Hz component
0.5f * sinf(2.0f * M_PI * 20.0f * t); // 20 Hz component
}
// Compute reference solution on CPU
std::vector<hipFloatComplex> cpu_output = cpuDFT(signal);
// Allocate device memory
float* d_signal;
hipFloatComplex* d_output;
HIP_CHECK(hipMalloc(&d_signal, N * sizeof(float)));
HIP_CHECK(hipMalloc(&d_output, N * sizeof(hipFloatComplex)));
// Copy input to device
HIP_CHECK(hipMemcpy(d_signal, signal.data(), N * sizeof(float),
hipMemcpyHostToDevice));
// Launch kernel
dim3 grid((N + blockSize - 1) / blockSize);
dim3 block(blockSize);
computeDFT<<<grid, block>>>(d_signal, d_output, N);
HIP_CHECK(hipGetLastError());
// Get GPU results
std::vector<hipFloatComplex> gpu_output(N);
HIP_CHECK(hipMemcpy(gpu_output.data(), d_output, N * sizeof(hipFloatComplex),
hipMemcpyDeviceToHost));
// Verify results
bool passed = true;
const float tolerance = 1e-5f; // Adjust based on precision requirements
for (int i = 0; i < N; i++) {
float diff_real = std::abs(hipCrealf(gpu_output[i]) - hipCrealf(cpu_output[i]));
float diff_imag = std::abs(hipCimagf(gpu_output[i]) - hipCimagf(cpu_output[i]));
if (diff_real > tolerance || diff_imag > tolerance) {
passed = false;
break;
}
}
std::cout << "DFT Verification: " << (passed ? "PASSED" : "FAILED") << "\n";
// Cleanup
HIP_CHECK(hipFree(d_signal));
HIP_CHECK(hipFree(d_output));
return passed ? 0 : 1;
}
.. literalinclude:: ../tools/example_codes/complex_math.hip
:start-after: // [sphinx-start]
:end-before: // [sphinx-end]
:language: cpp
@@ -27,7 +27,7 @@ and :doc:`GPU isolation <rocm:conceptual/gpu-isolation>`.
-
* - | ``AMD_LOG_MASK``
| Specifies HIP log filters. Here is the ` complete list of log masks <https://github.com/ROCm/clr/blob/develop/rocclr/utils/debug.hpp#L40>`_.
| Specifies HIP log filters. Here is the `complete list of log masks <https://github.com/ROCm/rocm-systems/blob/develop/projects/clr/rocclr/utils/debug.hpp#L48>`_.
- ``0x7FFFFFFF``
- | 0x1: Log API calls.
| 0x2: Kernel and copy commands and barriers.
@@ -49,8 +49,16 @@ and :doc:`GPU isolation <rocm:conceptual/gpu-isolation>`.
| 0x20000: Memory allocation.
| 0x40000: Memory pool allocation, including memory in graphs.
| 0x80000: Timestamp details.
| 0x100000: Comgr path information print.
| 0xFFFFFFFF: Log always even mask flag is zero.
* - | ``HIP_FORCE_DEV_KERNARG``
| Forces kernel arguments to be stored in device memory to reduce latency.
| Can improve performance by 2-3 µs for some kernels.
- ``1``
- | 0: Disable
| 1: Enable
* - | ``HIP_LAUNCH_BLOCKING``
| Used for serialization on kernel execution.
- ``0``
@@ -14,7 +14,7 @@ environment variables in HIP are collected in the following table.
* - | ``ROCR_VISIBLE_DEVICES``
| A list of device indices or UUIDs that will be exposed to applications.
- :doc:`GPU isolation <rocm:conceptual/gpu-isolation>`, :doc:`Setting the number of compute units <rocm:how-to/setting-cus>`
- Example: ``0,GPU-DEADBEEFDEADBEEF``
- Example: ``0,GPU-4b2c1a9f-8d3e-6f7a-b5c9-2e4d8a1f6c3b``
* - | ``GPU_DEVICE_ORDINAL``
| Devices indices exposed to OpenCL and HIP applications.
@@ -25,3 +25,11 @@ environment variables in HIP are collected in the following table.
| Device indices exposed to HIP applications.
- :doc:`GPU isolation <rocm:conceptual/gpu-isolation>`, :doc:`HIP debugging <hip:how-to/debugging>`
- Example: ``0,2``
.. admonition:: Recommendation
* On Linux, use ``ROCR_VISIBLE_DEVICES``.
* On Windows, use ``HIP_VISIBLE_DEVICES``.
* For portability across different vendors, use ``CUDA_VISIBLE_DEVICES``.
@@ -55,6 +55,12 @@ pages:
- | 0: Disable
| 1: Enable
* - | ``GPU_SINGLE_ALLOC_PERCENT``
| Limits the maximum size of a single memory allocation as a percentage of GPU memory.
- ``100``
- | Unit: Percentage
| Prevents single allocations from consuming all available GPU memory.
* - | ``GPU_MAX_HEAP_SIZE``
| Set maximum size of the GPU heap to % of board memory.
- ``100``
@@ -16,19 +16,19 @@ different features in HIP.
- ``--gpu-architecture=gfx906:sramecc+:xnack``, ``-fgpu-rdc``
* - | ``AMD_COMGR_SAVE_TEMPS``
| Controls the deletion of temporary files generated during the compilation of COMGR. These files do not appear in the current working directory, but are instead left in a platform-specific temporary directory.
| Controls the deletion of temporary files generated during the compilation of Comgr. These files do not appear in the current working directory, but are instead left in a platform-specific temporary directory.
- Unset by default.
- | 0: Temporary files are deleted automatically.
| Non zero integer: Turn off the temporary files deletion.
* - | ``AMD_COMGR_EMIT_VERBOSE_LOGS``
| Sets logging of COMGR to include additional Comgr-specific informational messages.
| Sets logging of Comgr to include additional Comgr-specific informational messages.
- Unset by default.
- | 0: Verbose log disabled.
| Non zero integer: Verbose log enabled.
* - | ``AMD_COMGR_REDIRECT_LOGS``
| Controls redirect logs of COMGR.
| Controls redirect logs of Comgr.
- Unset by default.
- | `stdout` / `-`: Redirected to the standard output.
| `stderr`: Redirected to the error stream.
@@ -24,88 +24,10 @@ The following C++ example shows a simplified method for computing ULP difference
HIP and standard C++ math functions by first finding where the maximum absolute error
occurs.
.. code-block:: cpp
#include <hip/hip_runtime.h>
#include <iostream>
#include <vector>
#include <cmath>
#include <limits>
#define HIP_CHECK(expression) \
{ \
const hipError_t err = expression; \
if (err != hipSuccess) { \
std::cerr << "HIP error: " \
<< hipGetErrorString(err) \
<< " at " << __LINE__ << "\n"; \
exit(EXIT_FAILURE); \
} \
}
// Simple ULP difference calculator
int64_t ulp_diff(float a, float b) {
if (a == b) return 0;
union { float f; int32_t i; } ua{a}, ub{b};
// For negative values, convert to a positive-based representation
if (ua.i < 0) ua.i = std::numeric_limits<int32_t>::max() - ua.i;
if (ub.i < 0) ub.i = std::numeric_limits<int32_t>::max() - ub.i;
return std::abs((int64_t)ua.i - (int64_t)ub.i);
}
// Test kernel
__global__ void test_sin(float* out, int n) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n) {
float x = -M_PI + (2.0f * M_PI * i) / (n - 1);
out[i] = sin(x);
}
}
int main() {
const int n = 1000000;
const int blocksize = 256;
std::vector<float> outputs(n);
float* d_out;
HIP_CHECK(hipMalloc(&d_out, n * sizeof(float)));
dim3 threads(blocksize);
dim3 blocks((n + blocksize - 1) / blocksize); // Fixed grid calculation
test_sin<<<blocks, threads>>>(d_out, n);
HIP_CHECK(hipPeekAtLastError());
HIP_CHECK(hipMemcpy(outputs.data(), d_out, n * sizeof(float), hipMemcpyDeviceToHost));
// Step 1: Find the maximum absolute error
double max_abs_error = 0.0;
float max_error_output = 0.0;
float max_error_expected = 0.0;
for (int i = 0; i < n; i++) {
float x = -M_PI + (2.0f * M_PI * i) / (n - 1);
float expected = std::sin(x);
double abs_error = std::abs(outputs[i] - expected);
if (abs_error > max_abs_error) {
max_abs_error = abs_error;
max_error_output = outputs[i];
max_error_expected = expected;
}
}
// Step 2: Compute ULP difference based on the max absolute error pair
int64_t max_ulp = ulp_diff(max_error_output, max_error_expected);
// Output results
std::cout << "Max Absolute Error: " << max_abs_error << std::endl;
std::cout << "Max ULP Difference: " << max_ulp << std::endl;
std::cout << "Max Error Values -> Got: " << max_error_output
<< ", Expected: " << max_error_expected << std::endl;
HIP_CHECK(hipFree(d_out));
return 0;
}
.. literalinclude:: ../tools/example_codes/math.hip
:start-after: // [sphinx-start]
:end-before: // [sphinx-end]
:language: cpp
Standard mathematical functions
===============================