Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ steps:
- label: "Documentation"
plugins:
- JuliaCI/julia#v1:
version: "1.10"
version: "1.12"
- sv-oss/node-n#v0.1.2:
node-version: v20
command: |
Expand All @@ -18,7 +18,7 @@ steps:
Pkg.build()

Pkg.activate("docs")
Pkg.add(; path=".")
Pkg.develop(PackageSpec(path="."))
Pkg.instantiate()

push!(LOAD_PATH, @__DIR__)
Expand Down
16 changes: 16 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,38 @@ function main()
"Home" => "index.md",
"Tutorials" => [
"Quick Start" => "tutorials/quickstart.md",
"Custom Structs in Kernels" => "tutorials/custom_structs.md",
"Performance Tips" => "tutorials/perf.md",
"Profiling" => "tutorials/profiling.md",
"Installation Tips" => "install_tips.md",
"Testing" => "testing.md",
],
"Usage" => [
"Array Programming" => "usage/arrays.md",
"Tasks and Streams" => "usage/multitasking.md",
"KernelAbstractions" => "usage/kernelabstractions.md",
],
"API" => [
"Devices" => "api/devices.md",
"System and Configuration" => "api/system.md",
"Streams" => "api/streams.md",
"Kernel Programming" => "api/kernel_programming.md",
"Reflection" => "api/reflection.md",
"Graphs" => "api/graphs.md",
"Exceptions" => "api/exceptions.md",
"Memory" => "api/memory.md",
"Host-Call" => "api/hostcall.md",
"Printing" => "api/printing.md",
"Intrinsics" => "api/intrinsics.md",
],
"Libraries" => [
"Linear Algebra" => "libraries/linalg.md",
"Sparse Arrays" => "libraries/sparse.md",
"Fourier Transforms" => "libraries/fft.md",
"Random Numbers" => "libraries/rand.md",
"Deep Learning (MIOpen)" => "libraries/dnn.md",
],
"FAQ" => "faq.md",
],
doctest=true,
warnonly=[:missing_docs],
Expand Down
28 changes: 28 additions & 0 deletions docs/src/api/reflection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Introspection and Reflection

AMDGPU.jl mirrors Julia's `code_*` reflection tools for GPU kernels, letting you inspect what a kernel lowers to at each compilation stage. This is the main way to debug performance and codegen issues — for example checking that a kernel stays type-stable or that a hot loop vectorizes.

Each `@device_code_*` macro wraps a kernel launch (`@roc ...`) and prints the corresponding representation instead of running it:

- `@device_code_lowered` — lowered Julia IR.
- `@device_code_typed` — type-inferred Julia IR (use this to spot type instabilities).
- `@device_code_warntype` — type-inferred IR with instabilities highlighted.
- `@device_code_llvm` — the generated LLVM IR.
- `@device_code_gcn` — the final AMD GCN assembly.
- `@device_code` — dump all of the above into a directory.

```julia
using AMDGPU

function vadd!(c, a, b)
i = workitemIdx().x
c[i] = a[i] + b[i]
return
end

a = AMDGPU.ones(Float32, 16); b = AMDGPU.ones(Float32, 16); c = similar(a)

@device_code_warntype @roc groupsize=16 vadd!(c, a, b)
```

The non-macro forms (`AMDGPU.code_typed`, `AMDGPU.code_llvm`, `AMDGPU.code_gcn`, …) take a function and a tuple of argument types directly, mirroring `Base.code_typed` and friends. These reflection tools are inherited from [GPUCompiler.jl](https://github.com/JuliaGPU/GPUCompiler.jl); see its documentation for the full set of options each macro accepts.
26 changes: 26 additions & 0 deletions docs/src/api/system.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# System and Configuration

## Checking the installation

`AMDGPU.versioninfo()` prints a full report of detected ROCm libraries, their versions, and the available devices. `AMDGPU.functional()` returns whether AMDGPU.jl can run at all, and `AMDGPU.functional(component)` queries an individual ROCm component (see [FAQ](@ref) for the component list). `has_rocm_gpu()` additionally requires that a GPU device is present.

```@docs
AMDGPU.versioninfo
AMDGPU.functional
AMDGPU.has_rocm_gpu
```

## Configuration preferences

Several behaviours are configured through [Preferences.jl](https://github.com/JuliaPackaging/Preferences.jl) and persist across sessions (they are written to your project's `LocalPreferences.toml`):

| Preference | Set via | Effect |
|:--|:--|:--|
| `nonblocking_synchronize` | preference | Use non-blocking stream synchronization (default `true`); disable for slightly lower latency. See [Streams](@ref). |
| `eager_gc` | `AMDGPU.eager_gc!(::Bool)` | Trigger GC before allocations under memory pressure. See [Memory Allocation and Intrinsics](@ref). |
| `hard_memory_limit` | `AMDGPU.hard_memory_limit!("8 GiB")` | Hard cap on GPU memory, checked before every allocation. |
| `soft_memory_limit` | `AMDGPU.soft_memory_limit!("6 GiB")` | Advisory limit for the memory pool. |

## Debugging kernel launches

Set the environment variable `HIP_LAUNCH_BLOCKING=1` (or toggle `AMDGPU.LAUNCH_BLOCKING[] = true` at runtime) to make kernel launches synchronous. This makes errors surface at the offending launch rather than at a later synchronization point, which is invaluable when tracking down a crashing or misbehaving kernel.
57 changes: 57 additions & 0 deletions docs/src/faq.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# FAQ

## How do I check that AMDGPU.jl works?

`AMDGPU.functional()` returns `true` when the ROCm stack is available and a GPU can be used. For a full report of detected devices, libraries and versions, use `AMDGPU.versioninfo()`.

```julia
using AMDGPU
AMDGPU.functional() # true if AMDGPU.jl can run on this machine
AMDGPU.versioninfo() # detailed diagnostics
```

## How should a package depend on AMDGPU.jl?

AMDGPU.jl loads on any machine, but only works when ROCm and a supported GPU are present. Code that should run with or without a GPU must therefore guard GPU use behind `AMDGPU.functional()` rather than assume it — importing the package is not enough.

```julia
using AMDGPU

if AMDGPU.functional()
x = AMDGPU.ones(Float32, 1024) # run on the GPU
else
x = ones(Float32, 1024) # CPU fallback
end
```

For a hard requirement of GPU hardware specifically, `has_rocm_gpu()` additionally checks that at least one device is present. For a heavier optional dependency, prefer a [package extension](https://pkgdocs.julialang.org/v1/creating-packages/#Conditional-loading-of-code-in-packages-(Extensions)) that loads only when AMDGPU is available, following the pattern used by the wider Julia GPU ecosystem.

## Which ROCm libraries are available?

Individual components are queried with `AMDGPU.functional(component)`, useful when a feature depends on a specific library:

```julia
AMDGPU.functional(:rocblas) # dense linear algebra (rocBLAS)
AMDGPU.functional(:rocsolver) # factorizations (rocSOLVER)
AMDGPU.functional(:rocsparse) # sparse arrays (rocSPARSE)
AMDGPU.functional(:rocfft) # FFTs (rocFFT)
AMDGPU.functional(:rocrand) # random numbers (rocRAND)
AMDGPU.functional(:MIOpen) # deep-learning primitives (MIOpen)
AMDGPU.functional(:all) # true only if every component is available
```

## My GPU is not detected or a library is missing

Run `AMDGPU.versioninfo()` and check that `hip` and the library you need report as functional. Missing components usually mean the corresponding ROCm package is not installed. See [Installation Info](@ref) for platform-specific setup, including the package list for distributions such as Fedora.

## I'm on Arch Linux and ROCm isn't working

For the last few ROCm releases, users have reported problems with the distro-provided ROCm builds and associated tools ([#770](https://github.com/JuliaGPU/AMDGPU.jl/issues/770), [#696](https://github.com/JuliaGPU/AMDGPU.jl/issues/696), [#767](https://github.com/JuliaGPU/AMDGPU.jl/issues/767)). Some have had success with the [`opencl-amd-dev`](https://aur.archlinux.org/packages/opencl-amd-dev) AUR package instead.

## How do I control GPU memory usage?

`ROCArray`s are managed by Julia's garbage collector, and a HIP memory pool caches freed allocations. You can free eagerly, cap usage, and query current usage — see the [Memory Allocation and Intrinsics](@ref) page for `AMDGPU.unsafe_free!`, memory limits, and the caching allocator.

## Where can I get help?

Ask on the [Julia Discourse](https://discourse.julialang.org/c/domain/gpu) GPU domain or the `#gpu` channel of the [Julia Slack](https://julialang.org/community/). Bug reports and feature requests are welcome on the [issue tracker](https://github.com/JuliaGPU/AMDGPU.jl/issues).
13 changes: 13 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ gridsize = cld(length(c), groupsize)
@assert (a .+ b) ≈ c
```

## Feature overview

| Area | What you get | Learn more |
|:--|:--|:--|
| Arrays | Dense `ROCArray`, broadcasting, reductions, sorting | [Array Programming](usage/arrays.md) |
| Kernels | Native `@roc` kernels and portable [KernelAbstractions](usage/kernelabstractions.md) | [Kernel Programming](api/kernel_programming.md) |
| Multi-GPU | Task-local devices and streams | [Tasks and Streams](usage/multitasking.md) |
| Linear algebra | `*`, `\`, `cholesky`, `lu`, `qr` via rocBLAS/rocSOLVER | [Linear Algebra](libraries/linalg.md) |
| Sparse | CSR/CSC/COO arrays, SpMV/SpMM via rocSPARSE | [Sparse Arrays](libraries/sparse.md) |
| FFT | `fft`/`plan_fft` via rocFFT | [Fourier Transforms](libraries/fft.md) |
| Random | `rand`/`randn` via rocRAND | [Random Numbers](libraries/rand.md) |
| Deep learning | Conv/pooling/softmax via MIOpen (NNlib/Flux) | [Deep Learning (MIOpen)](libraries/dnn.md) |

## Questions and Contributions

Usage questions can be posted on the
Expand Down
13 changes: 0 additions & 13 deletions docs/src/install_tips.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,16 +103,3 @@ kernel might throw an exception, specifically during conversions, like:

To avoid this, use 'unsafe' conversion option:
`unsafe_trunc(Int32, 1f0)`.

## Frequently-Asked-Questions

### Archlinux

For the last few ROCM releases we have seen folks run into
issue with the distro-provided builds of ROCM and associated tools.
[#770](https://github.com/JuliaGPU/AMDGPU.jl/issues/770),
[#696](https://github.com/JuliaGPU/AMDGPU.jl/issues/696),
[#767](https://github.com/JuliaGPU/AMDGPU.jl/issues/767)

Some users have reported success with using the
[`opencl-amd-dev`](https://aur.archlinux.org/packages/opencl-amd-dev) AUR package.
14 changes: 14 additions & 0 deletions docs/src/libraries/dnn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# Deep Learning (MIOpen)

AMDGPU.jl exposes AMD's [MIOpen](https://github.com/ROCm/MIOpen) deep-learning primitives through the `AMDGPU.MIOpen` submodule: convolutions, pooling, softmax, batch normalization, and activation functions, all operating on `ROCArray`.

In practice you rarely call these directly. They back the GPU implementations used by [NNlib.jl](https://github.com/FluxML/NNlib.jl) and [Flux.jl](https://github.com/FluxML/Flux.jl), so building and training a model on an AMD GPU with Flux uses MIOpen automatically once your data and parameters are `ROCArray`s.

Check that MIOpen is available with:

```julia
using AMDGPU
AMDGPU.functional(:MIOpen)
```

If it reports `false`, install the MIOpen ROCm package for your platform (see [Installation Info](@ref)).
35 changes: 35 additions & 0 deletions docs/src/libraries/fft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Fourier Transforms

AMDGPU.jl implements the [AbstractFFTs.jl](https://github.com/JuliaMath/AbstractFFTs.jl) interface on top of AMD's [rocFFT](https://github.com/ROCm/rocFFT), so `fft`, `ifft`, `rfft`, and the planning API work on `ROCArray` just as they do on the CPU. Load `AbstractFFTs` (or a package that re-exports it, such as `FFTW`) alongside AMDGPU:

```julia
using AMDGPU
using AbstractFFTs

x = ROCArray(ComplexF32[1, 2, 3, 4])
y = fft(x) # forward transform on the GPU
z = ifft(y) # z ≈ x
```

Real-to-complex transforms are available through `rfft`:

```julia
xr = AMDGPU.rand(Float32, 1024)
yr = rfft(xr) # length 513 complex output
```

## Plans

For repeated transforms of the same size, create a plan once and reuse it to amortize setup cost. Both out-of-place and in-place plans are supported:

```julia
x = ROCArray(rand(ComplexF32, 1024))

p = plan_fft(x) # out-of-place
y = p * x

p! = plan_fft!(x) # in-place, overwrites its argument
p! * x
```

Multidimensional transforms and transforms over selected dimensions work as usual, e.g. `fft(x, (1, 2))` for a 2D transform of a higher-dimensional array.
53 changes: 53 additions & 0 deletions docs/src/libraries/linalg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
```@meta
DocTestSetup = quote
using AMDGPU
using LinearAlgebra
end
```

# Linear Algebra

Standard `LinearAlgebra` functions work directly on `ROCArray`, dispatching to AMD's [rocBLAS](https://github.com/ROCm/rocBLAS) (dense BLAS) and [rocSOLVER](https://github.com/ROCm/rocSOLVER) (LAPACK-style factorizations). You write ordinary Julia linear algebra; the GPU libraries are used automatically.

Supported out of the box on `ROCArray`:

- Matrix–matrix and matrix–vector products (`*`, `mul!`), including mixed- and low-precision (`Float16`) matmul.
- BLAS level-1 operations: `dot`, `norm`, `axpy!`, `axpby!`, `rmul!`.
- Triangular solves and `\` (linear systems, LU-based).
- Factorizations: `cholesky`, `lu`, `qr`, `svd`.

```jldoctest linalg
julia> A = ROCArray(Float32[4 1; 1 3]);

julia> b = ROCArray(Float32[1, 2]);

julia> x = A \ b; # solve, LU via rocSOLVER

julia> Array(A * x) ≈ Array(b)
true

julia> C = cholesky(A); # Cholesky factorization

julia> Array(C.U' * C.U) ≈ Array(A)
true
```

Element types follow rocBLAS/rocSOLVER: `Float32`, `Float64`, `ComplexF32`, and `ComplexF64` (with `Float16` also supported for matmul).

## Singular value decomposition

`svd`, `svd!`, and `svdvals` run on `ROCMatrix` via rocSOLVER. The `alg` keyword selects the backend — `JacobiAlgorithm()` (the default, usually fastest on AMD GPUs) or `QRAlgorithm()`:

```julia
using AMDGPU.rocSOLVER: JacobiAlgorithm, QRAlgorithm

F = svd(A) # Jacobi by default; F.U, F.S, F.Vt
s = svdvals(A) # singular values only
Ff = svd(A; full = true, alg = QRAlgorithm())
```

Because `svdvals` is supported, so is `cond`. (`opnorm(A, 2)` is not yet available — it relies on scalar indexing internal to `LinearAlgebra`.)

## Direct library access

Lower-level routines are available in the `AMDGPU.rocBLAS` and `AMDGPU.rocSOLVER` submodules for cases the generic interface does not cover — for example batched factorizations, or the raw `gesvd!` (QR) and `gesvdj!` (Jacobi) SVD kernels.
31 changes: 31 additions & 0 deletions docs/src/libraries/rand.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Random Numbers

AMDGPU.jl generates random numbers on the device through AMD's [rocRAND](https://github.com/ROCm/rocRAND). The quickest way to get a random `ROCArray` is the package-level `rand`/`randn`, which mirror `Base`:

```julia
using AMDGPU

AMDGPU.rand(Float32, 1024) # uniform in [0, 1)
AMDGPU.randn(Float32, 8, 8) # standard normal
AMDGPU.rand(Int32, 100) # uniform integers
```

The standard `Random` in-place interface works on existing `ROCArray`s and fills them on the GPU:

```julia
using Random

a = ROCArray{Float32}(undef, 1024)
Random.rand!(a)
Random.randn!(a)
```

## Seeding

Seed the device generators for reproducible results with `AMDGPU.seed!`:

```julia
AMDGPU.seed!(1234)
```

This seeds both the rocRAND generator (used by `AMDGPU.rand`/`randn`) and the GPUArrays fallback generator, so results are reproducible regardless of which path a given operation takes.
34 changes: 34 additions & 0 deletions docs/src/libraries/sparse.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Sparse Arrays

AMDGPU.jl wraps AMD's [rocSPARSE](https://github.com/ROCm/rocSPARSE) and stores sparse matrices on the device with the `AMDGPU.rocSPARSE` array types:

- `ROCSparseMatrixCSR` — compressed sparse row (the usual default for GPU work).
- `ROCSparseMatrixCSC` — compressed sparse column.
- `ROCSparseMatrixCOO` — coordinate format.
- `ROCSparseVector` — sparse vector.

Construct them by converting a host `SparseMatrixCSC`, and convert back the same way:

```julia
using AMDGPU, SparseArrays
using AMDGPU.rocSPARSE

S = sprand(Float32, 1000, 1000, 0.01)
dS = ROCSparseMatrixCSR(S) # upload to the GPU

SparseMatrixCSC(dS) # download back to the host
```

## Operations

Sparse matrix–vector (SpMV) and matrix–matrix (SpMM) products use the standard `*` operator:

```julia
x = AMDGPU.rand(Float32, 1000)
y = dS * x # SpMV

B = AMDGPU.rand(Float32, 1000, 8)
Y = dS * B # SpMM
```

Incomplete-factorization preconditioners (`ic0`, `ilu0`) and further sparse routines (conversions between formats, triangular solves, gather/scatter) are available in the `AMDGPU.rocSPARSE` submodule for building iterative solvers on the GPU.
15 changes: 15 additions & 0 deletions docs/src/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,18 @@ julia> Pkg.test("AMDGPU"; test_args=`gpuarrays`)

!!! warning "Large memory tests"
Some tests such as HIP and GPUArrays tests may use > 20GB of host RAM. It is recommended to use fewer workers (<= 4) on machines that have < 32Gb of host RAM in case running tests would result in out of memory errors.

## Building the documentation

The documentation is built with [Documenter.jl](https://documenter.juliadocs.org) and [DocumenterVitepress.jl](https://github.com/LuxDL/DocumenterVitepress.jl). To build it locally:

```
julia --project=docs -e 'using Pkg; Pkg.instantiate()'
julia --project=docs docs/make.jl
julia --project=docs -e 'using LiveServer; serve(dir="docs/build/1")'
```

The last command serves the built site locally; open the printed URL in a browser.

!!! note "Doctests need a GPU"
`make.jl` runs with `doctest=true`, so every ```` ```jldoctest ```` block is executed on a real device. Building the docs therefore requires a functional AMD GPU, and a clean build means all examples still produce their documented output. When writing examples, prefer showing `Array(x)` rather than a raw `ROCArray` so the output does not depend on internal buffer types.
Loading