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

Add Buildkite GPU pipeline #411

Merged
merged 25 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
73a6b59
Simplify tests and add Buildkite pipeline
rkierulf Jun 17, 2024
f7bcd24
Apply suggestions from code review
cncastillo Jun 17, 2024
a29b12b
Change AMDGPU tests to use julia 1.10 and add oneAPI workaround
rkierulf Jun 17, 2024
2f0b520
Fix AMD device name issue
rkierulf Jun 17, 2024
ae99553
Try again to fix AMD device name issue
rkierulf Jun 17, 2024
78c4790
See if this fixes oneAPI issue
rkierulf Jun 18, 2024
84ac225
Add gpu function without backend parameter
rkierulf Jun 18, 2024
b7f30b1
Avoid installing all GPU backends
rkierulf Jun 18, 2024
aec8848
Type stability for 1im
rkierulf Jun 18, 2024
6cde94b
Change warning message slightly
rkierulf Jun 18, 2024
c52c9ba
Split BlochSimulationMethod::62 into multiple lines to see where it f…
rkierulf Jun 18, 2024
ef5bfc7
Add some more temporary printing
rkierulf Jun 18, 2024
7d2dc76
Try using cos and sin instead of broadcasting exp over complex numbers
rkierulf Jun 18, 2024
40c09ac
Use cis for complex exponentials
rkierulf Jun 18, 2024
a056dc9
Switch back to sin and cos since cis still doesn't work
rkierulf Jun 18, 2024
43672f2
Merge branch 'master' of https://github.com/JuliaHealth/KomaMRI.jl in…
rkierulf Jun 19, 2024
310f3a1
Add code coverage plugin to Buildkite pipeline
rkierulf Jun 19, 2024
0d70782
Add code coverage token
rkierulf Jun 19, 2024
5fd3245
Try with new token
rkierulf Jun 19, 2024
5ce5d45
Third time's the charm?
rkierulf Jun 19, 2024
ab48e13
Try one more time
rkierulf Jun 19, 2024
0becfe8
Add JULIA_PKG_SERVER
rkierulf Jun 19, 2024
08ee3b3
Try with 2nd CODECOV_TOKEN value
rkierulf Jun 19, 2024
714cbb4
Fixed
cncastillo Jun 20, 2024
9068796
Merge branch 'master' into buildkite
cncastillo Jun 20, 2024
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
121 changes: 119 additions & 2 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,122 @@
steps:
- label: "Example Test"
command: echo "Hello!"
- label: "AMDGPU: Run tests on v{{matrix.version}}"
matrix:
setup:
version:
- "1.10"
plugins:
- JuliaCI/julia#v1:
version: "{{matrix.version}}"
- JuliaCI/julia-coverage#v1:
codecov: true
dirs:
- KomaMRICore/src
- KomaMRICore/ext
command: |
julia -e 'println("--- :julia: Instantiating project")
using Pkg
Pkg.develop([
PackageSpec(path=pwd(), subdir="."),
PackageSpec(path=pwd(), subdir="KomaMRIBase"),
PackageSpec(path=pwd(), subdir="KomaMRICore"),
])'

julia -e 'println("--- :julia: Running tests")
using Pkg
Pkg.test("KomaMRICore"; coverage=true, test_args=["AMDGPU"])'
agents:
queue: "juliagpu"
rocm: "*"
timeout_in_minutes: 120

- label: "CUDA: Run tests on v{{matrix.version}}"
matrix:
setup:
version:
- "1.9"
plugins:
- JuliaCI/julia#v1:
version: "{{matrix.version}}"
- JuliaCI/julia-coverage#v1:
codecov: true
dirs:
- KomaMRICore/src
- KomaMRICore/ext
command: |
julia -e 'println("--- :julia: Instantiating project")
using Pkg
Pkg.develop([
PackageSpec(path=pwd(), subdir="."),
PackageSpec(path=pwd(), subdir="KomaMRIBase"),
PackageSpec(path=pwd(), subdir="KomaMRICore"),
])'

julia -e 'println("--- :julia: Running tests")
using Pkg
Pkg.test("KomaMRICore"; coverage=true, test_args=["CUDA"])'
agents:
queue: "juliagpu"
cuda: "*"
timeout_in_minutes: 120

- label: "Metal: Run tests on v{{matrix.version}}"
matrix:
setup:
version:
- "1.9"
plugins:
- JuliaCI/julia#v1:
version: "{{matrix.version}}"
command: |
julia -e 'println("--- :julia: Instantiating project")
using Pkg
Pkg.develop([
PackageSpec(path=pwd(), subdir="."),
PackageSpec(path=pwd(), subdir="KomaMRIBase"),
PackageSpec(path=pwd(), subdir="KomaMRICore"),
])'

julia -e 'println("--- :julia: Running tests")
using Pkg
Pkg.test("KomaMRICore"; test_args=["Metal"])'
agents:
queue: "juliaecosystem"
os: "macos"
arch: "aarch64"
timeout_in_minutes: 120

- label: "oneAPI: Run tests on v{{matrix.version}}"
matrix:
setup:
version:
- "1.9"
plugins:
- JuliaCI/julia#v1:
version: "{{matrix.version}}"
- JuliaCI/julia-coverage#v1:
codecov: true
dirs:
- KomaMRICore/src
- KomaMRICore/ext
command: |
julia -e 'println("--- :julia: Instantiating project")
using Pkg
Pkg.develop([
PackageSpec(path=pwd(), subdir="."),
PackageSpec(path=pwd(), subdir="KomaMRIBase"),
PackageSpec(path=pwd(), subdir="KomaMRICore"),
])'

julia -e 'println("--- :julia: Running tests")
using Pkg
Pkg.test("KomaMRICore"; coverage=true, test_args=["oneAPI"])'
agents:
queue: "juliagpu"
intel: "*"
timeout_in_minutes: 120

env:
CI: BUILDKITE
CODECOV_FLAGS: core
JULIA_PKG_SERVER: ""
SECRET_CODECOV_TOKEN: "lUmUVYkTlE8u0mR/ymv5rtE1A59wXZmQ3miRkmKciC/4+xHPNjpeIJ03FupuC1ElGBeX0m6DDFavZ9burLosGxbBYIPziBQZ5P9NdPDZjBdo7NM3QSSBeUfDsDYbHsYglfJZ35UL6Pd2YTAkJG0ePrTpfUaBb9rcll926NdqUP0vE2hbR2leKFFgBVNtK9Zf+NE7hO3meZQEZ+sN5tA7xGr24A3Ay7ckPg5HbPPD3KII2/fLtW+w0fQUfJdXNFrajJ0FyNE0kNLDlIzoYN6XM4yUeLBXoyXFHnqT5dSu7pqrByEk/ptYpjUzKFoRSnDQy+p8vrx9e/iAVf3lwwgwWA==;U2FsdGVkX1+IZLGTj2FNEy4XvUQbzkZFEwUpwIdRDCKrEea5O/OKGV5vYJufty3m9yniE+av4937HabS9dO1RA=="
2 changes: 1 addition & 1 deletion KomaMRICore/ext/KomaAMDGPUExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ KomaMRICore.name(::ROCBackend) = "AMDGPU"
KomaMRICore.isfunctional(::ROCBackend) = AMDGPU.functional()
KomaMRICore.set_device!(::ROCBackend, dev_idx::Integer) = AMDGPU.device_id!(dev_idx)
KomaMRICore.set_device!(::ROCBackend, dev::AMDGPU.HIPDevice) = AMDGPU.device!(dev)
KomaMRICore.device_name(::ROCBackend) = AMDGPU.device().name
KomaMRICore.device_name(::ROCBackend) = AMDGPU.HIP.name(AMDGPU.device())

function Adapt.adapt_storage(
::ROCBackend, x::Vector{KomaMRICore.LinearInterpolator{T,V}}
Expand Down
4 changes: 2 additions & 2 deletions KomaMRICore/ext/KomaMetalExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
#Temporary workaround for https://github.com/JuliaGPU/Metal.jl/issues/348
#Once run_spin_excitation! and run_spin_precession! are kernel-based, this code
#can be removed
Base.cumsum(x::MtlVector) = convert(MtlVector, cumsum(KomaMRICore.cpu(x)))
Base.cumsum(x::MtlVector{T}) where T = convert(MtlVector{T}, cumsum(KomaMRICore.cpu(x)))

Check warning on line 26 in KomaMRICore/ext/KomaMetalExt.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRICore/ext/KomaMetalExt.jl#L26

Added line #L26 was not covered by tests
Base.cumsum(x::MtlArray{T}; dims) where T = convert(MtlArray{T}, cumsum(KomaMRICore.cpu(x), dims=dims))
Base.findall(x::MtlVector{Bool}) = convert(MtlVector, findall(KomaMRICore.cpu(x)))

function __init__()
push!(KomaMRICore.LOADED_BACKENDS[], MetalBackend())
@warn "Due to https://github.com/JuliaGPU/Metal.jl/issues/348, some functions may need to run on the CPU. Performance may be impacted as a result."
@warn "Metal does not support all array operations used by KomaMRI (https://github.com/JuliaGPU/Metal.jl/issues/348). GPU performance may be slower than expected"

Check warning on line 32 in KomaMRICore/ext/KomaMetalExt.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRICore/ext/KomaMetalExt.jl#L32

Added line #L32 was not covered by tests
end

end
7 changes: 7 additions & 0 deletions KomaMRICore/ext/KomaoneAPIExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,15 @@ function KomaMRICore._print_devices(::oneAPIBackend)
@info "$(length(oneAPI.devices())) oneAPI capable device(s)." devices...
end

#Temporary workaround since oneAPI.jl (similar to Metal) does not support some array operations
#Once run_spin_excitation! and run_spin_precession! are kernel-based, this code can be removed
Base.cumsum(x::oneVector{T}) where T = convert(oneVector{T}, cumsum(KomaMRICore.cpu(x)))
Base.cumsum(x::oneArray{T}; dims) where T = convert(oneArray{T}, cumsum(KomaMRICore.cpu(x), dims=dims))
Base.findall(x::oneVector{Bool}) = convert(oneVector, findall(KomaMRICore.cpu(x)))

function __init__()
push!(KomaMRICore.LOADED_BACKENDS[], oneAPIBackend())
@warn "oneAPI does not support all array operations used by KomaMRI. GPU performance may be slower than expected"
end

end
2 changes: 1 addition & 1 deletion KomaMRICore/src/KomaMRICore.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ include("rawdata/ISMRMRD.jl")
include("datatypes/Spinor.jl")
include("other/DiffusionModel.jl")
# Simulator
include("simulation/Functors.jl")
include("simulation/GPUFunctions.jl")
include("simulation/Functors.jl")
include("simulation/SimulatorCore.jl")

# ISMRMRD
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function run_spin_precession!(
#Mxy precession and relaxation, and Mz relaxation
tp = cumsum(seq.Δt) # t' = t - t0
dur = sum(seq.Δt) # Total length, used for signal relaxation
Mxy = [M.xy M.xy .* exp.(1im .* ϕ .- tp' ./ p.T2)] #This assumes Δw and T2 are constant in time
Mxy = [M.xy M.xy .* exp.(-tp' ./ p.T2) .* (cos.(ϕ) .+ im * sin.(ϕ))] #This assumes Δw and T2 are constant in time
M.xy .= Mxy[:, end]
#Acquired signal
sig[:, :, 1] .= transpose(Mxy[:, findall(seq.ADC)])
Expand Down
2 changes: 1 addition & 1 deletion KomaMRICore/src/simulation/Bloch/BlochSimulationMethod.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function run_spin_precession!(
#Mxy precession and relaxation, and Mz relaxation
tp = cumsum(seq.Δt) # t' = t - t0
dur = sum(seq.Δt) # Total length, used for signal relaxation
Mxy = [M.xy M.xy .* exp.(1im .* ϕ .- tp' ./ p.T2)] #This assumes Δw and T2 are constant in time
Mxy = [M.xy M.xy .* exp.(-tp' ./ p.T2) .* (cos.(ϕ) .+ im * sin.(ϕ))] #This assumes Δw and T2 are constant in time
M.xy .= Mxy[:, end]
M.z .= M.z .* exp.(-dur ./ p.T1) .+ p.ρ .* (1 .- exp.(-dur ./ p.T1))
#Acquired signal
Expand Down
28 changes: 28 additions & 0 deletions KomaMRICore/src/simulation/Functors.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,34 @@
_isleaf(::AbstractArray{T}) where T = isbitstype(T)
_isleaf(::AbstractRange) = true

"""
gpu(x)

Moves 'x' to the GPU. For this function to work, a GPU backend will need to be
loaded with 'using AMDGPU / CUDA / Metal / oneAPI.

This works for functions, and any struct marked with `@functor`.

Use [`cpu`](@ref) to copy back to ordinary `Array`s.

See also [`f32`](@ref) and [`f64`](@ref) to change element type only.

# Examples
```julia
using CUDA
x = gpu(x)
```
"""
function gpu(x)
get_backend(true)

Check warning on line 29 in KomaMRICore/src/simulation/Functors.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRICore/src/simulation/Functors.jl#L28-L29

Added lines #L28 - L29 were not covered by tests

if (BACKEND[] isa KA.GPU)
return gpu(x, BACKEND[])

Check warning on line 32 in KomaMRICore/src/simulation/Functors.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRICore/src/simulation/Functors.jl#L31-L32

Added lines #L31 - L32 were not covered by tests
else
@error "function 'gpu' called with no functional backends available. Add 'using CUDA / Metal / AMDGPU / oneAPI' to your code and try again"

Check warning on line 34 in KomaMRICore/src/simulation/Functors.jl

View check run for this annotation

Codecov / codecov/patch

KomaMRICore/src/simulation/Functors.jl#L34

Added line #L34 was not covered by tests
end
end

"""
gpu(x, backend)

Expand Down
7 changes: 2 additions & 5 deletions KomaMRICore/test/Project.toml
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
[deps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
KomaMRIBase = "d0bc0b20-b151-4d03-b2a4-6ca51751cb9c"
Metal = "dde4c033-4e86-420c-a63e-0dd931031962"
oneAPI = "8f75cd03-7ff8-4ecb-9b8f-daf728133b1b"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
Suppressor = "fd094767-a336-5f1f-9728-57cf17d0bbfb"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
TestItemRunner = "f8b46487-2199-4994-9208-9a1283c18c0a"
TestItems = "1c621080-faea-4a02-84b6-bbd5e436b8fe"
TestItems = "1c621080-faea-4a02-84b6-bbd5e436b8fe"
29 changes: 29 additions & 0 deletions KomaMRICore/test/initialize.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Pkg
using Suppressor

const USE_GPU = if "AMDGPU" in ARGS
@suppress Pkg.add("AMDGPU")
using AMDGPU
@info "Testing AMD" maxlog=1
true
elseif "CUDA" in ARGS
@suppress Pkg.add("CUDA")
using CUDA
@info "Testing CUDA" maxlog=1
true
elseif "Metal" in ARGS
@suppress Pkg.add("Metal")
using Metal
@info "Testing Metal" maxlog=1
true
elseif "oneAPI" in ARGS
@suppress Pkg.add("oneAPI")
using oneAPI
@info "Testing oneAPI" maxlog=1
true
else
@info "Testing on the CPU with $(Threads.nthreads()) thread(s)" maxlog=1
false
end

using KomaMRICore
Loading