Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to AMGX_jll 2.4 and later Julia versions #33

Merged
merged 17 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 14 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
93 changes: 54 additions & 39 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
@@ -1,42 +1,57 @@
env:
SECRET_CODECOV_TOKEN: "MIXvKy8FpOJzyBykdGQdVdn0jVli57e1Mc1QQQQA6RyLBdViYwCOjLQS+Yh5sgeD5eEm9JLtu6ISePq01EjqpHF7/6zJlcEJTqj2JidcH/sp/FnJiIY0MfV48DSrz1XA7rN6hHQ8wh09+BMG1Ur4CbtwVQl1HF3wZqmt+b2Ahknyxd0mrIoT3j6RJ90vVSGagLLqWolaQLLOFoGNyHbeFV15r1YXLZDkwyE1SSNz4JF3qEN7vFbM9ZnbR4edd7zWABdDiGd3FDnbn1OJFbZ3JzJXph6JAxZyF34RFDzZsERiKyIrAM+0LfyDYqCAcYnjDpJoEASZugTTwIKXOjUkyQ==;U2FsdGVkX1+go3U7v0bYSZs2Lx4R/lwnJXQm4ATdXL2Y7x5H9QDOgazDvusO8UmBtwHFi3szvPuuxr/gcXYgxw=="

steps:
- label: "Julia 1.6"
plugins:
- JuliaCI/julia#v1:
version: 1.6
- JuliaCI/julia-test#v1: ~
- JuliaCI/julia-coverage#v1:
codecov: true
agents:
queue: "juliagpu"
cuda: "10.0"
if: build.message !~ /\[skip tests\]/
timeout_in_minutes: 60
- group: ":julia: Julia"
steps:
- label: "Julia {{matrix.julia}}"
plugins:
- JuliaCI/julia#v1:
version: "{{matrix.julia}}"
- JuliaCI/julia-test#v1: ~
- JuliaCI/julia-coverage#v1: ~
agents:
queue: "juliagpu"
cuda: "*"
commands: |
julia --project -e "
using CUDA
CUDA.set_runtime_version!(local_toolkit=true)"
timeout_in_minutes: 60
matrix:
setup:
julia:
- "1.10"
- "1.11"

- label: "Julia 1.7"
plugins:
- JuliaCI/julia#v1:
version: 1.7
- JuliaCI/julia-test#v1: ~
- JuliaCI/julia-coverage#v1:
codecov: true
agents:
queue: "juliagpu"
cuda: "10.0"
if: build.message !~ /\[skip tests\]/
timeout_in_minutes: 60
- group: "CUDA"
steps:
- label: "CUDA {{matrix.cuda}}"
plugins:
- JuliaCI/julia#v1:
version: "1.11"
- JuliaCI/julia-test#v1: ~
- JuliaCI/julia-coverage#v1: ~
agents:
queue: "juliagpu"
cuda: "*"
timeout_in_minutes: 45
matrix:
setup:
cuda:
- "12.6"
- "12.5"
- "12.4"
- "12.3"
- "12.2"
- "12.1"
- "12.0"
- "11.8"
- "11.7"
- "11.6"
- "11.5"
- "11.4"
commands: |
julia --project -e "
using CUDA
CUDA.set_runtime_version!(v\"{{matrix.cuda}}\")"

- label: "Julia 1.8"
plugins:
- JuliaCI/julia#v1:
version: 1.8
- JuliaCI/julia-test#v1: ~
- JuliaCI/julia-coverage#v1:
codecov: true
agents:
queue: "juliagpu"
cuda: "10.0"
if: build.message !~ /\[skip tests\]/
timeout_in_minutes: 60
env:
SECRET_CODECOV_TOKEN: "MIXvKy8FpOJzyBykdGQdVdn0jVli57e1Mc1QQQQA6RyLBdViYwCOjLQS+Yh5sgeD5eEm9JLtu6ISePq01EjqpHF7/6zJlcEJTqj2JidcH/sp/FnJiIY0MfV48DSrz1XA7rN6hHQ8wh09+BMG1Ur4CbtwVQl1HF3wZqmt+b2Ahknyxd0mrIoT3j6RJ90vVSGagLLqWolaQLLOFoGNyHbeFV15r1YXLZDkwyE1SSNz4JF3qEN7vFbM9ZnbR4edd7zWABdDiGd3FDnbn1OJFbZ3JzJXph6JAxZyF34RFDzZsERiKyIrAM+0LfyDYqCAcYnjDpJoEASZugTTwIKXOjUkyQ==;U2FsdGVkX1+go3U7v0bYSZs2Lx4R/lwnJXQm4ATdXL2Y7x5H9QDOgazDvusO8UmBtwHFi3szvPuuxr/gcXYgxw=="
17 changes: 9 additions & 8 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
authors = ["JuliaHub"]
name = "AMGX"
uuid = "c963dde9-0319-47f5-bf0c-b07d3c80ffa6"
authors = ["JuliaHub"]
version = "0.1.4"
version = "0.2.0"

[compat]
AMGX_jll = "2.4"
CEnum = "0.5"
CUDA = "4,5"
JSON = "0.21"
julia = "1.10"

[deps]
AMGX_jll = "656d14af-56e4-5275-8e68-4e861d7b5043"
Expand All @@ -11,12 +18,6 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb"
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

[compat]
CEnum = "0.4"
CUDA = "2.2, 3, 4"
JSON = "0.21"
julia = "1.5"

[extras]
Defer = "6f25fe36-ecbb-5dff-aeb8-f7b50c87fb5f"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ The library can now be initialized with:
```julia
using AMGX
AMGX.initialize()
AMGX.initialize_plugins()
```

### `Config`
Expand Down
140 changes: 70 additions & 70 deletions lib/libAMGX.jl

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lib/libAMGX_common.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ end
AMGX_SOLVE_SUCCESS = 0
AMGX_SOLVE_FAILED = 1
AMGX_SOLVE_DIVERGED = 2
AMGX_SOLVE_NOT_CONVERGED = 2
AMGX_SOLVE_NOT_CONVERGED = 3
end

@cenum AMGX_GET_PARAMS_DESC_FLAG::UInt32 begin
Expand Down
39 changes: 0 additions & 39 deletions src/AMGX.jl
Original file line number Diff line number Diff line change
Expand Up @@ -38,45 +38,6 @@ end
#########

module API
using Libdl
# Taken from LLVM.jl, can be removed when package only supports 1.6 and higher
macro runtime_ccall(target, args...)
if VERSION >= v"1.6.0-DEV.819"
quote
ccall($(esc(target)), $(map(esc, args)...))
end
else
# decode ccall function/library target
Meta.isexpr(target, :tuple) || error("Expected (function_name, library) tuple")
function_name, library = target.args

# global const ref to hold the function pointer
@gensym fptr_cache
@eval __module__ begin
# uses atomics (release store, acquire load) for thread safety.
# see https://github.com/JuliaGPU/CUDAapi.jl/issues/106 for details
const $fptr_cache = Threads.Atomic{UInt}(0)
end

quote
# use a closure to hold the lookup and avoid code bloat in the caller
@noinline function cache_fptr!()
library = Libdl.dlopen($(esc(library)))
$(esc(fptr_cache))[] = Libdl.dlsym(library, $(esc(function_name)))

$(esc(fptr_cache))[]
end

fptr = $(esc(fptr_cache))[]
if fptr == 0 # folded into the null check performed by ccall
fptr = cache_fptr!()
end

ccall(reinterpret(Ptr{Cvoid}, fptr), $(map(esc, args)...))
end
end
end

using CEnum
import ..libAMGX

Expand Down
11 changes: 9 additions & 2 deletions src/Config.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@ function create!(config::Config, content::String)
end
Config(content::String) = create!(Config(), content)

function create!(config::Config, d::Dict)
str = sprint(JSON.print, d)
function create!(config::Config, d::Dict; json = false)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The create! functions are not documented in the README so they are purely internal it seems? But then this kwarg doesn't do anything since the default will always be used?

Copy link
Collaborator

@KristofferC KristofferC Oct 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It also changes the default from JSON to non JSON. Why is that desirable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change was added by @vchuravy in the branch, but when I tested it seemed like the right choice since the JSON parsing seemed a bit brittle. AMGX will always try parsing as JSON first, and then the string format. I added the (not exposed) kwarg to have an option to fall back to the old way just in case if someone wants to make use of internals. Not sure how to best handle this, but the tests do not pass with the old JSON formatter.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed the json option in the latest version. I wonder if the JLL might be built without JSON parsing working - I cannot get it to load the test JSON files from the AMGX repository. There is a sort of related issue in the AMGX repository NVIDIA/AMGX#99 where one of the first checks was to see if RAPIDJSON_DEFINED is in the build flags. CMake should have found it when building since it is bundled with the AMGX repo. I am able to set most options using the fallback string interface now at least, so the library is functional.

if json
str = sprint(JSON.print, d)
else
str = ""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better to use an IOBuffer or a sprint() do call here.

for (key, val) in d
str *= string(key, "=", val, ", ")
end
end
create!(config, str)
end
Config(d::Dict) = create!(Config(), d)
Expand Down
4 changes: 2 additions & 2 deletions src/Solver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ end
function get_iterations_number(solver::Solver)
n_ptr = Ref{Cint}()
@checked API.AMGX_solver_get_iterations_number(solver.handle, n_ptr)
# for some reason AMGX returns 1 + number of iterations.
return Int(n_ptr[]) - 1
return Int(n_ptr[])
end

function get_iteration_residual(solver::Solver, iter::Int=get_iterations_number(solver), block_idx::Int=0)
Expand All @@ -73,6 +72,7 @@ end
SUCCESS = Int(API.AMGX_SOLVE_SUCCESS)
FAILED = Int(API.AMGX_SOLVE_FAILED)
DIVERGED = Int(API.AMGX_SOLVE_DIVERGED)
NOT_CONVERGED = Int(API.AMGX_SOLVE_NOT_CONVERGED)
end

function get_status(solver::Solver)
Expand Down
33 changes: 30 additions & 3 deletions test/test_solver.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,37 @@ using AMGX: Config, Resources, AMGXVector, AMGXMatrix, Solver, dDDI, dFFI
AMGX.upload!(x, [0.0, 0.0, 0.0])
AMGX.upload!(b, [1.0, 2.0, 4.0])

AMGX.setup!(s, M)
AMGX.solve!(x, s, b)
x_h = AMGX.download(b)
@test x_h ≈ [1.0, 2.0, 4.0]

AMGX.upload!(x, [1.0, 2.0, 3.0])
AMGX.solve!(x, s, b; zero_inital_guess=true)
x_h = AMGX.download(x)
@test x_h ≈ [1.0, 2.0, 4.0]
end

@scope @testset "solver with residuals" begin
# Same test as above, but this time output residuals.
c = @! Config(Dict("monitor_residual" => 1))
r = @! Resources(c)
M = @! AMGXMatrix(r, mode)
x = @! AMGXVector(r, mode)
b = @! AMGXVector(r, mode)
s = @! Solver(r, mode, c)

AMGX.upload!(M, Cint[0, 1, 2, 3], Cint[0, 1, 2], [1.0, 1.0, 1.0])
AMGX.upload!(x, [0.0, 0.0, 0.0])
AMGX.upload!(b, [1.0, 2.0, 4.0])

AMGX.setup!(s, M)
AMGX.solve!(x, s, b)
x_h = AMGX.download(b)
@test x_h ≈ [1.0, 2.0, 4.0]
status = AMGX.get_status(s)
# Note: If we don't set monitor_residual, the status flag does not
# reflect if the solution has converged or not.
@test status == AMGX.SUCCESS

AMGX.upload!(x, [1.0, 2.0, 3.0])
Expand All @@ -46,7 +72,7 @@ using AMGX: Config, Resources, AMGXVector, AMGXMatrix, Solver, dDDI, dFFI
AMGX.upload!(b, [1.0, 2.0, 4.0])
AMGX.setup!(s, M)
AMGX.solve!(x, s, b; zero_inital_guess=true)
@test AMGX.get_status(s) == AMGX.DIVERGED
@test AMGX.get_status(s) == AMGX.NOT_CONVERGED
@test AMGX.get_iterations_number(s) == 0
@test AMGX.get_iteration_residual(s) > 1.0

Expand All @@ -55,7 +81,7 @@ using AMGX: Config, Resources, AMGXVector, AMGXMatrix, Solver, dDDI, dFFI
end

@scope @testset "get_iterations_number" begin
c = @! Config(Dict("monitor_residual" => 1, "tolerance" => 1e-14, "store_res_history" => 1))
c = @! Config(Dict("monitor_residual" => 1, "tolerance" => "1e-14", "store_res_history" => 1))
r = @! Resources(c)
M = @! AMGXMatrix(r, mode)
x = @! AMGXVector(r, mode)
Expand All @@ -67,8 +93,9 @@ using AMGX: Config, Resources, AMGXVector, AMGXMatrix, Solver, dDDI, dFFI
AMGX.upload!(b, [1.0, 2.0, 4.0])
AMGX.setup!(s, M)
AMGX.solve!(x, s, b)
@test AMGX.get_iteration_residual(s) < 1e-14
niter = AMGX.get_iterations_number(s)
moyner marked this conversation as resolved.
Show resolved Hide resolved
@test niter > 0
@test AMGX.get_iteration_residual(s) < 1e-14
@test AMGX.get_iteration_residual(s, niter) == AMGX.get_iteration_residual(s)
end
end
Expand Down