API reference

Library lifecycle

AMGX.finalizeFunction
finalize()

Shut the AMGX library down. All AMGX objects must be closed first.

source
Base.closeFunction
close(object)

Destroy an AMGX object — a Config, Resources, AMGXVector, AMGXMatrix or Solver.

AMGX objects are not garbage collected, so each must be closed explicitly. Ordering matters: an object cannot be closed while others created from it are still alive, and doing so raises a RefCountError. Defer.jl makes this considerably less tedious.

source
close(p::AMGXPreconditioner)

Free the scratch vectors the preconditioner allocated. The Solver it wraps is not closed — it was created by the caller and stays theirs to close.

source

Configuration and resources

AMGX.ConfigType
Config(content::String)
Config(d::Dict)

An AMGX configuration, holding the parameters that control how a Solver behaves.

It can be built from a comma-separated AMGX config string, or from a dictionary whose pairs are joined into one:

cfg = AMGX.Config("max_iters=10, monitor_residual=1")
cfg = AMGX.Config(Dict("max_iters" => 10, "monitor_residual" => 1))

The accepted parameters are those of the AMGX library itself; see the AMGX reference manual. An unknown parameter raises an AMGXException.

Must be freed with close once no longer needed; see the note on memory management in the README.

source
AMGX.ResourcesType
Resources(cfg::Config; device_id=nothing)

Create AMGX resources from cfg, optionally pinning them to a specific CUDA device. See create!.

source
AMGX.create!Function
create!(resources::Resources, cfg::Config; device_id=nothing)

Create AMGX resources from cfg.

device_id selects the CUDA device AMGX should run on, as a zero-based index matching CUDA's own numbering. When it is nothing (the default) AMGX picks the device itself, which is the current device for the calling thread.

Note

device_id only moves AMGX. Data uploaded from CuArrays is allocated on CUDA.jl's current device, so uploading device arrays into resources bound to a different device fails with CUDA kernel launch error. Switch CUDA.jl to the same device first:

CUDA.device!(1)
resources = Resources(cfg; device_id=1)

Uploads from ordinary host arrays are copied by AMGX itself and are unaffected by the current device.

source
AMGX.ModeType
Mode

Selects where AMGX runs and at what precision. The available modes are hDDI, hDFI, hFFI, dDDI, dDFI and dFFI, read as four characters:

positionmeaning
1h on the host, d on the device
2precision of vectors — D for Float64, F for Float32
3precision of matrix coefficients — D or F
4I, 32-bit integer indices (Cint)

So dDDI runs on the GPU with Float64 throughout, while dDFI keeps Float64 vectors alongside Float32 matrix coefficients.

Julia arrays passed to upload! must match the precision the mode declares. Use vector_type and matrix_type to obtain them.

Note

Upstream AMGX does not support mixed-precision GPU solves on CUDA 10.1 or later. Use dDDI or dFFI for solving; dDFI still supports uploads and downloads.

source
AMGX.vector_typeFunction
vector_type(m::Mode)

The Julia element type AMGX expects for vectors in mode m, e.g. Float64 for dDDI.

source
AMGX.matrix_typeFunction
matrix_type(m::Mode)

The Julia element type AMGX expects for matrix coefficients in mode m, e.g. Float32 for dDFI.

source

Vectors

AMGX.AMGXVectorType
AMGXVector(resources::Resources, mode::Mode)

A dense vector living wherever mode says — on the device for the d* modes.

Created empty; fill it with upload! or set_zero!, and read it back with Vector, Array, CuVector or copy!.

v = AMGX.AMGXVector(resources, AMGX.dDDI)
AMGX.upload!(v, [1.0, 2.0, 3.0])
Vector(v)

Must be freed with close before the Resources it was created from.

source
AMGX.upload!Function
upload!(v::AMGXVector, data; block_dim=1)

Copy data into v. data may be a Vector on the host or a CuVector already on the device, and its element type must match the precision of the vector's Mode.

block_dim gives the block size for block systems; length(data) must be an exact multiple of it, and the resulting vector has length(data) ÷ block_dim block rows.

source
upload!(m::AMGXMatrix, row_ptrs, col_indices, data; block_dims=(1,1), diag_data=nothing)
upload!(m::AMGXMatrix, A::CUDA.CUSPARSE.CuSparseMatrixCSR)

Copy a CSR matrix into m.

row_ptrs and col_indices are zero-based Cint arrays, as AMGX expects — not Julia's one-based indexing. data holds the non-zero values, and its element type must match the matrix precision of the Mode. All three may live on the host or on the device.

block_dims gives the block size for block systems. diag_data, if given, holds the diagonal separately from the CSR arrays, with n * block_dimx * block_dimy entries in AoS layout; pass nothing when the diagonal is already part of the matrix.

A CuSparseMatrixCSR can be uploaded directly, which is usually the simplest route from Julia.

source
AMGX.downloadFunction
download(v::AMGXVector)

Copy v back to a newly allocated host Vector of the mode's element type.

Vector(v) and Array(v) are equivalent; CuVector(v) downloads to the device instead.

source
AMGX.download!Function
download!(buffer, v::AMGXVector)
copy!(buffer, v::AMGXVector)

Copy v into an existing buffer, avoiding an allocation. buffer may live on the host or the device, and length(buffer) must equal length(v).

source
AMGX.set_zero!Function
set_zero!(v::AMGXVector, n=length(v); block_dim=1)

Resize v to n block rows of size block_dim and fill it with zeros. Useful for the solution vector before a solve!, which needs a vector of the right size to write into.

source
Base.lengthFunction
length(v::AMGXVector)

Total number of scalar entries, i.e. block rows times block dimension.

source

Matrices

AMGX.AMGXMatrixType
AMGXMatrix(resources::Resources, mode::Mode)

A sparse matrix in AMGX, stored in CSR format — note that Julia's SparseMatrixCSC is CSC, so a transpose or conversion is needed when going from one to the other.

Created empty; fill it with upload!.

matrix = AMGX.AMGXMatrix(resources, AMGX.dDDI)
AMGX.upload!(matrix, CUDA.CUSPARSE.CuSparseMatrixCSR(A))

Must be freed with close before the Resources it was created from.

source
AMGX.replace_coefficients!Function
replace_coefficients!(m::AMGXMatrix, data; diag_data=nothing)

Replace the non-zero values of m, keeping its sparsity structure. data must have exactly as many entries as the matrix has non-zeros.

Pair this with resetup! to re-solve with new coefficients without paying for a full setup!.

source
Base.sizeFunction
size(matrix::AMGXMatrix)

Dimensions of matrix in scalar entries, i.e. block rows times block dimensions.

source

Solvers

AMGX.SolverType
Solver(resources::Resources, mode::Mode, config::Config)

An AMGX solver. config determines which algorithm is used and its parameters.

A solver is used in three steps: bind a matrix with setup!, solve with solve!, and — if only the coefficients changed — rebind cheaply with resetup!.

solver = AMGX.Solver(resources, AMGX.dDDI, config)
AMGX.setup!(solver, matrix)
AMGX.solve!(x, solver, b)

Must be freed with close before the Resources and Config it was created from.

source
AMGX.setup!Function
setup!(solver::Solver, matrix::AMGXMatrix)

Bind matrix to solver and perform the setup phase, building the multigrid hierarchy. This is the expensive part of a solve.

source
AMGX.resetup!Function
resetup!(solver::Solver, matrix::AMGXMatrix)

Redo the setup for a matrix whose coefficients changed but whose sparsity structure did not — typically after replace_coefficients!. Much cheaper than a full setup!.

matrix must be the one already bound by setup!; otherwise an ArgumentError is thrown.

source
AMGX.solve!Function
solve!(sol::AMGXVector, solver::Solver, rhs::AMGXVector; zero_inital_guess=false)

Solve A * sol = rhs, where A is the matrix bound by setup!, writing the result into sol. The current contents of sol are used as the initial guess unless zero_inital_guess is true.

Note that a solve that does not converge is not an error: check get_status afterwards.

source
AMGX.get_statusFunction
get_status(solver::Solver)

The SolverStatus of the last solve!. Always worth checking: a non-converged solve returns normally and leaves a partial result in the solution vector.

source
AMGX.SolverStatusType
SolverStatus

Outcome of the last solve!, as returned by get_status:

  • SUCCESS — the convergence criterion was met.
  • FAILED — the solver stopped on an internal error.
  • DIVERGED — the solver reported divergence.
  • NOT_CONVERGED — the criterion was not met, typically because max_iters was reached.
source
AMGX.get_iteration_residualFunction
get_iteration_residual(solver::Solver, iter=get_iterations_number(solver), block_idx=0)

Residual recorded at iteration iter of the last solve!, defaulting to the final one.

Requires store_res_history=1 in the Config for iterations other than the last.

source

Utilities

AMGX.versioninfoFunction
versioninfo(io=stdout)

Print the AMGX version, build date and API version, along with the CUDA runtime and driver it was built against.

source
AMGX.pin_memoryFunction
pin_memory(v::Vector)

Page-lock v so transfers to and from the GPU are faster. Release it again with unpin_memory before the array is freed.

source
AMGX.register_print_callbackFunction
register_print_callback(f)

Route everything AMGX would print through f, a function taking a String and returning nothing. Can be called before initialize.

AMGX.register_print_callback(_ -> nothing)          # silence AMGX
AMGX.register_print_callback(s -> print(stdout, s)) # restore
source

Errors

AMGX.AMGXExceptionType
AMGXException

Raised when an AMGX C call returns anything other than success. The message is AMGX's own description of the error code.

source
AMGX.error_stringFunction
error_string(err_code)

AMGX's human-readable description of an AMGX_RC return code.

source