diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 43cfba3..9d26a9c 100644 --- a/.buildkite/pipeline.yml +++ b/.buildkite/pipeline.yml @@ -7,13 +7,10 @@ steps: version: "1.10" command: | julia -e 'using Pkg - println("--- :julia: Instantiating environment") - Pkg.add("CUDA") Pkg.develop(path=".") - println("+++ :julia: Running tests") - Pkg.test("AcceleratedKernels", test_args=["--CUDA"])' + Pkg.test("AcceleratedKernels", test_args=["--cuda"])' agents: queue: "juliagpu" cuda: "*" @@ -26,13 +23,10 @@ steps: version: "1.11" command: | julia -e 'using Pkg - println("--- :julia: Instantiating environment") - Pkg.add("CUDA") Pkg.develop(path=".") - println("+++ :julia: Running tests") - Pkg.test("AcceleratedKernels", test_args=["--CUDA"])' + Pkg.test("AcceleratedKernels", test_args=["--cuda"])' agents: queue: "juliagpu" cuda: "*" @@ -47,13 +41,10 @@ steps: version: "1.10" command: | julia -e 'using Pkg - println("--- :julia: Instantiating environment") - Pkg.add("AMDGPU") Pkg.develop(path=".") - println("+++ :julia: Running tests") - Pkg.test("AcceleratedKernels", test_args=["--AMDGPU"])' + Pkg.test("AcceleratedKernels", test_args=["--amdgpu"])' agents: queue: "juliagpu" rocm: "*" @@ -67,13 +58,10 @@ steps: version: "1.11" command: | julia -e 'using Pkg - println("--- :julia: Instantiating environment") - Pkg.add("AMDGPU") Pkg.develop(path=".") - println("+++ :julia: Running tests") - Pkg.test("AcceleratedKernels", test_args=["--AMDGPU"])' + Pkg.test("AcceleratedKernels", test_args=["--amdgpu"])' agents: queue: "juliagpu" rocm: "*" @@ -89,13 +77,10 @@ steps: version: "1.10" command: | julia -e 'using Pkg - println("--- :julia: Instantiating environment") - Pkg.add("oneAPI") Pkg.develop(path=".") - println("+++ :julia: Running tests") - Pkg.test("AcceleratedKernels", test_args=["--oneAPI"])' + Pkg.test("AcceleratedKernels", test_args=["--oneapi"])' agents: queue: "juliagpu" intel: "*" @@ -108,13 +93,10 @@ steps: version: "1.11" command: | julia -e 'using Pkg - println("--- :julia: Instantiating environment") - Pkg.add("oneAPI") Pkg.develop(path=".") - println("+++ :julia: Running tests") - Pkg.test("AcceleratedKernels", test_args=["--oneAPI"])' + Pkg.test("AcceleratedKernels", test_args=["--oneapi"])' agents: queue: "juliagpu" intel: "*" @@ -129,13 +111,10 @@ steps: version: "1.10" command: | julia -e 'using Pkg - println("--- :julia: Instantiating environment") - Pkg.add("Metal") Pkg.develop(path=".") - println("+++ :julia: Running tests") - Pkg.test("AcceleratedKernels", test_args=["--Metal"])' + Pkg.test("AcceleratedKernels", test_args=["--metal"])' agents: queue: "juliaecosystem" os: "macos" @@ -149,13 +128,10 @@ steps: version: "1.11" command: | julia -e 'using Pkg - println("--- :julia: Instantiating environment") - Pkg.add("Metal") Pkg.develop(path=".") - println("+++ :julia: Running tests") - Pkg.test("AcceleratedKernels", test_args=["--Metal"])' + Pkg.test("AcceleratedKernels", test_args=["--metal"])' agents: queue: "juliaecosystem" os: "macos" diff --git a/.github/workflows/CI-CPU.yml b/.github/workflows/CI-CPU.yml index 2944bf2..e46bc3b 100644 --- a/.github/workflows/CI-CPU.yml +++ b/.github/workflows/CI-CPU.yml @@ -82,7 +82,7 @@ jobs: - uses: julia-actions/julia-buildpkg@v1 - uses: julia-actions/julia-runtest@v1 with: - test_args: '--OpenCL' + test_args: '--opencl' # cpuKA: # name: KA CPU Backend # runs-on: ubuntu-latest @@ -102,7 +102,7 @@ jobs: # - uses: julia-actions/julia-buildpkg@v1 # - uses: julia-actions/julia-runtest@v1 # with: - # test_args: '--cpuKA' + # test_args: '--cpu-ka' docs: name: Documentation runs-on: ubuntu-latest diff --git a/test/Project.toml b/test/Project.toml index d77e276..0a79e7d 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,7 +1,17 @@ [deps] +AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" +Metal = "dde4c033-4e86-420c-a63e-0dd931031962" +OpenCL = "08131aa3-fb12-5dee-8b74-c09406e224a2" +ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc" Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +oneAPI = "8f75cd03-7ff8-4ecb-9b8f-daf728133b1b" +pocl_jll = "627d6b7a-bbe6-5189-83e7-98cc0a5aeadd" + +[compat] +ParallelTestRunner = "2" diff --git a/test/aqua.jl b/test/aqua.jl new file mode 100644 index 0000000..14bd277 --- /dev/null +++ b/test/aqua.jl @@ -0,0 +1,4 @@ +using Aqua +@testset "Aqua" begin + Aqua.test_all(AK) +end diff --git a/test/accumulate.jl b/test/generic/accumulate.jl similarity index 100% rename from test/accumulate.jl rename to test/generic/accumulate.jl diff --git a/test/binarysearch.jl b/test/generic/binarysearch.jl similarity index 100% rename from test/binarysearch.jl rename to test/generic/binarysearch.jl diff --git a/test/looping.jl b/test/generic/looping.jl similarity index 100% rename from test/looping.jl rename to test/generic/looping.jl diff --git a/test/map.jl b/test/generic/map.jl similarity index 100% rename from test/map.jl rename to test/generic/map.jl diff --git a/test/predicates.jl b/test/generic/predicates.jl similarity index 100% rename from test/predicates.jl rename to test/generic/predicates.jl diff --git a/test/reduce.jl b/test/generic/reduce.jl similarity index 100% rename from test/reduce.jl rename to test/generic/reduce.jl diff --git a/test/sort.jl b/test/generic/sort.jl similarity index 100% rename from test/sort.jl rename to test/generic/sort.jl diff --git a/test/runtests.jl b/test/runtests.jl index 716fd8e..4f8a685 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,76 +1,143 @@ import AcceleratedKernels as AK -using KernelAbstractions -using Test -using Random -import Pkg - -# Set to true when testing backends that support this -const TEST_DL = Ref{Bool}(false) - -# Pass command-line argument to test suite to install the right backend, e.g. -# julia> import Pkg -# julia> Pkg.test(test_args=["--oneAPI"]) -if "--CUDA" in ARGS - Pkg.add("CUDA") +using ParallelTestRunner + +const init_code = quote + import AcceleratedKernels as AK + using KernelAbstractions + using Test + using Random +end + +# Discover root-level tests (aqua.jl, partition.jl) and generic tests +const testsuite = find_tests(@__DIR__) +const generic_tests = find_tests(joinpath(@__DIR__, "generic")) + +# Parse args with lowercase hyphenated backend flags +args = parse_args(ARGS; custom=["cuda", "amdgpu", "metal", "oneapi", "opencl", "cpu-ka"]) + +# Common helper code appended to every backend setup +const _array_from_host_code = quote + global array_from_host + array_from_host(h_arr::AbstractArray, dtype=nothing) = array_from_host(BACKEND, h_arr, dtype) + function array_from_host(backend, h_arr::AbstractArray, dtype=nothing) + d_arr = KernelAbstractions.zeros(backend, isnothing(dtype) ? eltype(h_arr) : dtype, size(h_arr)) + copyto!(d_arr, h_arr isa Array ? h_arr : Array(h_arr)) + d_arr + end +end + +# Build list of active backends, each with setup code +backends = Pair{String, Expr}[] + +# CPU always active +using InteractiveUtils +@info "Julia information:\n" * sprint(InteractiveUtils.versioninfo) +push!(backends, "cpu" => quote + global BACKEND = get_backend([]) + global IS_CPU_BACKEND = true + global prefer_threads = true + global TEST_DL = Ref{Bool}(false) + $_array_from_host_code +end) + +# cpu-ka only when --cpu-ka flag passed +if args.custom["cpu-ka"] !== nothing + push!(backends, "cpu-ka" => quote + global BACKEND = get_backend([]) + global IS_CPU_BACKEND = true + global prefer_threads = false + global TEST_DL = Ref{Bool}(false) + $_array_from_host_code + end) +end + +# GPU backends: auto-detect functional ones, or enable explicitly via CLI flags. +# Always assert functional() before proceeding, then print versioninfo() once. + +if try; using CUDA; CUDA.functional(); catch; false; end || args.custom["cuda"] !== nothing using CUDA - CUDA.versioninfo() - const BACKEND = CUDABackend() - TEST_DL[] = true -elseif "--oneAPI" in ARGS - Pkg.add("oneAPI") - using oneAPI - oneAPI.versioninfo() - const BACKEND = oneAPIBackend() + @assert CUDA.functional() + @info "CUDA information:\n" * sprint(CUDA.versioninfo) + push!(backends, "cuda" => quote + using CUDA + global BACKEND = CUDABackend() + global IS_CPU_BACKEND = false + global prefer_threads = true + global TEST_DL = Ref{Bool}(true) + $_array_from_host_code + end) +end - # FIXME: need atomic orderings for `DecoupledLookback` in oneAPI - # TEST_DL[] = true -elseif "--AMDGPU" in ARGS - Pkg.add("AMDGPU") +if try; using AMDGPU; AMDGPU.functional(); catch; false; end || args.custom["amdgpu"] !== nothing using AMDGPU - AMDGPU.versioninfo() - const BACKEND = ROCBackend() - TEST_DL[] = true -elseif "--Metal" in ARGS - Pkg.add("Metal") + @assert AMDGPU.functional() + @info "AMDGPU information:\n" * sprint(AMDGPU.versioninfo) + push!(backends, "amdgpu" => quote + using AMDGPU + global BACKEND = ROCBackend() + global IS_CPU_BACKEND = false + global prefer_threads = true + global TEST_DL = Ref{Bool}(true) + $_array_from_host_code + end) +end + +if try; using Metal; Metal.functional(); catch; false; end || args.custom["metal"] !== nothing using Metal - Metal.versioninfo() - const BACKEND = MetalBackend() -elseif "--OpenCL" in ARGS - Pkg.add(name="OpenCL", rev="master") - Pkg.add(name="SPIRVIntrinsics", rev="master") - Pkg.add("pocl_jll") - using pocl_jll - using OpenCL - OpenCL.versioninfo() - const BACKEND = OpenCLBackend() -elseif !@isdefined(BACKEND) - # Otherwise do CPU tests - using InteractiveUtils - InteractiveUtils.versioninfo() - const BACKEND = get_backend([]) + @assert Metal.functional() + @info "Metal information:\n" * sprint(Metal.versioninfo) + push!(backends, "metal" => quote + using Metal + global BACKEND = MetalBackend() + global IS_CPU_BACKEND = false + global prefer_threads = true + global TEST_DL = Ref{Bool}(false) + $_array_from_host_code + end) end -const IS_CPU_BACKEND = BACKEND == get_backend([]) +if try; using oneAPI; oneAPI.functional(); catch; false; end || args.custom["oneapi"] !== nothing + using oneAPI + @assert oneAPI.functional() + @info "oneAPI information:\n" * sprint(oneAPI.versioninfo) + push!(backends, "oneapi" => quote + using oneAPI + global BACKEND = oneAPIBackend() + global IS_CPU_BACKEND = false + global prefer_threads = true + global TEST_DL = Ref{Bool}(false) + $_array_from_host_code + end) +end -global prefer_threads::Bool = !(IS_CPU_BACKEND && "--cpuKA" in ARGS) +if try; using pocl_jll, OpenCL; !isempty(OpenCL.cl.platforms()); catch; false; end || args.custom["opencl"] !== nothing + using pocl_jll, OpenCL + @assert !isempty(OpenCL.cl.platforms()) + @info "OpenCL information:\n" * sprint(OpenCL.versioninfo) + push!(backends, "opencl" => quote + using pocl_jll + using OpenCL + global BACKEND = OpenCLBackend() + global IS_CPU_BACKEND = false + global prefer_threads = true + global TEST_DL = Ref{Bool}(false) + $_array_from_host_code + end) +end -array_from_host(h_arr::AbstractArray, dtype=nothing) = array_from_host(BACKEND, h_arr, dtype) -function array_from_host(backend, h_arr::AbstractArray, dtype=nothing) - d_arr = KernelAbstractions.zeros(backend, isnothing(dtype) ? eltype(h_arr) : dtype, size(h_arr)) - copyto!(d_arr, h_arr isa Array ? h_arr : Array(h_arr)) # Allow unmaterialised types, e.g. ranges - d_arr +# Duplicate generic tests per active backend +for (backend_name, setup_code) in backends + for (test_name, test_body) in generic_tests + testsuite["$backend_name/$test_name"] = quote + $setup_code + $test_body + end + end end -@testset "Aqua" begin - using Aqua - Aqua.test_all(AK) +# Filter tests by user-specified positional args; remove bare generic/ entries if no filter was specified +if filter_tests!(testsuite, args) + filter!(((k,v),) -> !startswith(k, "generic/"), testsuite) end -include("partition.jl") -include("looping.jl") -include("map.jl") -include("sort.jl") -include("reduce.jl") -include("accumulate.jl") -include("predicates.jl") -include("binarysearch.jl") +runtests(AK, args; init_code, testsuite)