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
24 changes: 24 additions & 0 deletions .buildkite/pipeline.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Tests of the KernelAbstractions-related parts of the GPU back-ends. Draft pull requests skip
# them, unless selected by name in the last commit message: `[only cuda]`, `[only metal, oneapi]`
# or `[only tests]` for all of them. `[skip amdgpu]` or `[skip tests]` does the opposite.
# (`opencl` selects the OpenCL.jl tests on CUDA hardware.)
steps:
- label: "CUDA Julia {{matrix.version}}"
matrix:
Expand Down Expand Up @@ -29,6 +33,10 @@ steps:
Pkg.test("CUDA"; coverage=true, test_args=["core/kernelabstractions", "core/kernelinterface"])'
agents:
queue: "cuda"
if: |
build.message !~ /\[skip [^\]]*(tests|cuda)/ &&
(build.message =~ /\[only [^\]]*(tests|cuda)/ ||
build.message !~ /\[only / && !build.pull_request.draft)
timeout_in_minutes: 120
soft_fail:
- exit_status: 3
Expand Down Expand Up @@ -92,6 +100,10 @@ steps:
Pkg.test("Metal"; coverage=true, test_args=["kernelabstractions", "kernelinterface"])'
agents:
queue: "metal"
if: |
build.message !~ /\[skip [^\]]*(tests|metal)/ &&
(build.message =~ /\[only [^\]]*(tests|metal)/ ||
build.message !~ /\[only / && !build.pull_request.draft)
timeout_in_minutes: 120
soft_fail:
- exit_status: 3
Expand Down Expand Up @@ -126,6 +138,10 @@ steps:
Pkg.test("oneAPI"; coverage=true, test_args=["kernelabstractions", "kernelinterface"])'
agents:
queue: "oneapi"
if: |
build.message !~ /\[skip [^\]]*(tests|oneapi)/ &&
(build.message =~ /\[only [^\]]*(tests|oneapi)/ ||
build.message !~ /\[only / && !build.pull_request.draft)
timeout_in_minutes: 120
soft_fail:
- exit_status: 3
Expand Down Expand Up @@ -161,6 +177,10 @@ steps:
Pkg.test("AMDGPU"; coverage=true, test_args=["kernelabstractions", "kernelinterface"])'
agents:
queue: "rocm"
if: |
build.message !~ /\[skip [^\]]*(tests|amdgpu)/ &&
(build.message =~ /\[only [^\]]*(tests|amdgpu)/ ||
build.message !~ /\[only / && !build.pull_request.draft)
timeout_in_minutes: 120
soft_fail:
- exit_status: 3
Expand Down Expand Up @@ -196,6 +216,10 @@ steps:
Pkg.test("OpenCL"; coverage=true, test_args=`--platform=nvidia nvidia/kernelabstractions nvidia/kernelinterface`)'
agents:
queue: "cuda"
if: |
build.message !~ /\[skip [^\]]*(tests|opencl)/ &&
(build.message =~ /\[only [^\]]*(tests|opencl)/ ||
build.message !~ /\[only / && !build.pull_request.draft)
timeout_in_minutes: 120
soft_fail:
- exit_status: 3
Expand Down
14 changes: 13 additions & 1 deletion src/pocl/compiler/execution.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,24 @@ Adapt.adapt_structure(to::KernelAdaptor, r::Base.RefValue{<:Union{DataType, Type
CLRefType{r[]}()

# case where type is the function being broadcasted
# (on Julia 1.14, the function type parameter is `Core.TypeEgal{T} <: Type{T}`)
Adapt.adapt_structure(
to::KernelAdaptor,
bc::Broadcast.Broadcasted{Style, <:Any, Type{T}}
bc::Broadcast.Broadcasted{Style, <:Any, <:Type{T}}
) where {Style, T} =
Broadcast.Broadcasted{Style}((x...) -> T(x...), adapt(to, bc.args), bc.axes)

# functions that capture a type, e.g., `Base.Fix1(convert, T)` as used by LinearAlgebra,
# which isn't a valid kernel argument either
function Adapt.adapt_structure(to::KernelAdaptor, f::Base.Fix1{<:Any, <:Type{T}}) where {T}
g = adapt(to, f.f)
return (x...) -> g(T, x...)
end
function Adapt.adapt_structure(to::KernelAdaptor, f::Base.Fix2{<:Any, <:Type{T}}) where {T}
g = adapt(to, f.f)
return (x...) -> g(x..., T)
end

"""
clconvert(x, [pointers])

Expand Down
10 changes: 10 additions & 0 deletions src/pocl/device/quirks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ end
@device_override @noinline Base.throw_boundserror(A, I) =
@gputhrow "BoundsError" "Out-of-bounds array access"

# essentials.jl
# Julia 1.14 routes indexed bounds errors through `_throw_boundserror_indices`
# rather than `throw_boundserror`, bypassing the override above.
@static if isdefined(Base, :_throw_boundserror_indices)
@device_override @noinline Base._throw_boundserror_indices(A) =
@gputhrow "BoundsError" "Out-of-bounds array access"
@device_override @noinline Base._throw_boundserror_indices(A, i1, I...) =
@gputhrow "BoundsError" "Out-of-bounds array access"
end

# trig.jl
@device_override @noinline Base.Math.sincos_domain_error(x) =
@gputhrow "DomainError" "sincos(x) is only defined for finite x"
Expand Down
14 changes: 11 additions & 3 deletions src/pocl/device/random.jl
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,16 @@ end
end
end

# Signature of Random's generic `AbstractFloat` fallbacks. Kept as a constant because
# spelling it inline (e.g. with `@invoke`) constructs the `UnionAll` at run time, which
# inference no longer folds away as of Julia 1.14 (JuliaLang/julia#62001).
const AbstractFloatFallback = Tuple{AbstractRNG, Type{<:AbstractFloat}}

# Use the table-free fallback, but compute it in Float32 because its polar transform can
# overflow in Float16. Keep this scoped to our RNG: overlay methods take precedence over
# regular dispatch and an AbstractRNG method would shadow methods for other device RNGs.
@device_override @inline function Random.randn(rng::Philox2x32, ::Type{T}) where {T <: Union{Float16, Float32}}
return T(@invoke Random.randn(rng::AbstractRNG, Float32::Type{<:AbstractFloat}))
return T(invoke(Random.randn, AbstractFloatFallback, rng, Float32))
end

## randexp
Expand All @@ -262,10 +267,13 @@ end

# Compute through Float32 to avoid requiring Float16 `log1p` support.
@device_override @inline function Random.randexp(rng::Philox2x32, ::Type{T}) where {T <: Union{Float16, Float32}}
return T(@invoke Random.randexp(rng::AbstractRNG, Float32::Type{<:AbstractFloat}))
return T(invoke(Random.randexp, AbstractFloatFallback, rng, Float32))
end

@device_override Random.Sampler(
# NOTE: not a consistent overlay (as SPIRVIntrinsics' `@device_override` may define), as
# this returns a different sampler than the host method: concrete evaluation would
# otherwise substitute the latter, which our overlaid `rand` methods fail to handle.
Base.Experimental.@overlay method_table Random.Sampler(
::Type{<:AbstractRNG}, r::AbstractUnitRange{T},
::Random.Repetition
) where {T <: Union{Int64, UInt64}} = Random.SamplerRangeFast(r)
Loading