diff --git a/.buildkite/pipeline.yml b/.buildkite/pipeline.yml index 582ab1df..7b004fdc 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: "cuda" if: build.message !~ /\[skip tests\]/ @@ -25,13 +22,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: "cuda" if: build.message !~ /\[skip tests\]/ @@ -45,13 +39,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: "rocm" rocmgpu: "*" @@ -64,13 +55,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: "rocm" rocmgpu: "*" @@ -85,13 +73,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: "oneapi" if: build.message !~ /\[skip tests\]/ @@ -103,13 +88,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: "oneapi" if: build.message !~ /\[skip tests\]/ @@ -123,13 +105,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: "metal" if: build.message !~ /\[skip tests\]/ @@ -141,13 +120,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: "metal" if: build.message !~ /\[skip tests\]/ diff --git a/.github/workflows/CI-CPU.yml b/.github/workflows/CI-CPU.yml index 2944bf2b..dbda2e70 100644 --- a/.github/workflows/CI-CPU.yml +++ b/.github/workflows/CI-CPU.yml @@ -12,6 +12,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} +env: + JULIA_PKG_PRECOMPILE_AUTO: false + jobs: test: name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - nthreads ${{ matrix.env.JULIA_NUM_THREADS }} - ${{ github.event_name }} @@ -82,7 +85,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 +105,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 d77e276f..4a9cdf68 100644 --- a/test/Project.toml +++ b/test/Project.toml @@ -1,7 +1,18 @@ [deps] +AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e" +AcceleratedKernels = "6a4ca0a5-0e36-4168-a932-d9be78d558f1" Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595" +CUDACore = "bd0ed864-bdfe-4181-a5ed-ce625a5fdea2" +CUDATools = "9ec180c6-1c07-47c7-9e6e-ebefa4d1f6d0" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" -Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +Metal = "dde4c033-4e86-420c-a63e-0dd931031962" +OpenCL = "08131aa3-fb12-5dee-8b74-c09406e224a2" +ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc" 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 00000000..14bd2771 --- /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 b858c78c..bb52212b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,76 +1,147 @@ 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 CUDA - CUDA.versioninfo() - const BACKEND = CUDABackend() - TEST_DL[] = true -elseif "--oneAPI" in ARGS - Pkg.add("oneAPI") - using oneAPI - oneAPI.versioninfo() - const BACKEND = oneAPIBackend() +using InteractiveUtils +using ParallelTestRunner + +@info "Julia information:\n" * sprint(InteractiveUtils.versioninfo) + +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", "cpu"]) - # FIXME: need atomic orderings for `DecoupledLookback` in oneAPI - # TEST_DL[] = true -elseif "--AMDGPU" in ARGS - Pkg.add("AMDGPU") +# 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}[] + +# GPU backends are only tested when explicitly requested via a CLI flag, in which case +# they are expected to be functional: load or initialization failures propagate. + +if args.custom["cuda"] !== nothing + using CUDACore, CUDATools + @assert CUDACore.functional() + @info "CUDACore information:\n" * sprint(CUDATools.versioninfo) + push!(backends, "cuda" => quote + using CUDACore + global BACKEND = CUDABackend() + global IS_CPU_BACKEND = false + global prefer_threads = true + global TEST_DL = Ref{Bool}(true) + $_array_from_host_code + end) +end + +if args.custom["amdgpu"] !== nothing using AMDGPU + @assert AMDGPU.functional() + println("AMDGPU information:") AMDGPU.versioninfo() - const BACKEND = ROCBackend() - TEST_DL[] = true -elseif "--Metal" in ARGS - Pkg.add("Metal") + 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 args.custom["metal"] !== nothing using Metal - Metal.versioninfo() - const BACKEND = MetalBackend() -elseif "--OpenCL" in ARGS - Pkg.add(name="OpenCL", rev="main") - Pkg.add(name="SPIRVIntrinsics", rev="main") - 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 + +if 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 -const IS_CPU_BACKEND = BACKEND == get_backend([]) +if 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 -global prefer_threads::Bool = !(IS_CPU_BACKEND && "--cpuKA" in ARGS) +# 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 + +# CPU runs if no backend selected or if explicitly specified +if args.custom["cpu"] !== nothing || isempty(backends) + 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) +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)