diff --git a/Project.toml b/Project.toml index 2c50b8797..543fc9c8d 100644 --- a/Project.toml +++ b/Project.toml @@ -12,6 +12,7 @@ MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +UnsafeAtomics = "013be700-e6cd-48c3-b4a1-df204f14c38f" UnsafeAtomicsLLVM = "d80eeb9a-aca5-4d75-85e5-170c8b632249" [compat] @@ -19,5 +20,5 @@ Adapt = "0.4, 1.0, 2.0, 3.0" Atomix = "0.1" MacroTools = "0.5" StaticArrays = "0.12, 1.0" -julia = "1.7" UnsafeAtomicsLLVM = "0.1" +julia = "1.7" diff --git a/test/atomix_test.jl b/test/atomix_test.jl new file mode 100644 index 000000000..631178e79 --- /dev/null +++ b/test/atomix_test.jl @@ -0,0 +1,115 @@ +using KernelAbstractions, Test +using KernelAbstractions: @atomic, @atomicswap, @atomicreplace + +# Note: kernels affect second element because some CPU defaults will affect the +# first element of a pointer if not specified, so I am covering the bases +@kernel function atomix_add_kernel!(input, b) + @atomic input[2] += b +end + +@kernel function atomix_sub_kernel!(input, b) + @atomic input[2] -= b +end + +@kernel function atomix_xchg_kernel!(input, b) + @atomicswap input[2] = b +end + +@kernel function atomix_max_kernel!(input, b) + tid = @index(Global) + @atomic max(input[2], b[tid]) +end + +@kernel function atomix_min_kernel!(input, b) + tid = @index(Global) + @atomic min(input[2], b[tid]) +end + +@kernel function atomix_cas_kernel!(input, b, c) + @atomicreplace input[2] b => c + #atomic_cas!(pointer(input,2),b,c) +end + +function atomix_testsuite(backend, ArrayT) + + @testset "atomic addition tests" begin + types = [Int32, Int64, UInt32, UInt64, Float32] + + for T in types + A = ArrayT{T}([0,0]) + + kernel! = atomix_add_kernel!(backend(), 4) + wait(kernel!(A, one(T), ndrange=(1024))) + + @test Array(A)[2] == 1024 + end + end + + @testset "atomic subtraction tests" begin + types = [Int32, Int64, UInt32, UInt64, Float32] + + for T in types + A = ArrayT{T}([2048,2048]) + + kernel! = atomix_sub_kernel!(backend(), 4) + wait(kernel!(A, one(T), ndrange=(1024))) + + @test Array(A)[2] == 1024 + end + end + + @testset "atomic xchg tests" begin + types = [Int32, Int64, UInt32, UInt64] + + for T in types + A = ArrayT{T}([0,0]) + + kernel! = atomix_xchg_kernel!(backend(), 4) + wait(kernel!(A, T(1), ndrange=(256))) + + @test Array(A)[2] == one(T) + end + end + + @testset "atomic max tests" begin + types = [Int32, Int64, UInt32, UInt64] + + for T in types + A = ArrayT{T}([0,0]) + B = ArrayT{T}([i for i = 1:1024]) + + kernel! = atomix_max_kernel!(backend(), 4) + wait(kernel!(A, B, ndrange=length(B))) + + @test Array(A)[2] == T(1024) + end + end + + @testset "atomic min tests" begin + types = [Int32, Int64, UInt32, UInt64] + + for T in types + A = ArrayT{T}([1024,1024]) + B = ArrayT{T}([i for i = 1:1024]) + + kernel! = atomix_min_kernel!(backend(), 4) + wait(kernel!(A, B, ndrange=length(B))) + + @test Array(A)[2] == T(1) + end + end + + + @testset "atomic cas tests" begin + types = [Int32, Int64, UInt32, UInt64] + + for T in types + A = ArrayT{T}([0,0]) + + kernel! = atomix_cas_kernel!(backend(), 4) + wait(kernel!(A, zero(T), one(T), ndrange=(1024))) + + @test Array(A)[2] == 1 + end + end +end diff --git a/test/testsuite.jl b/test/testsuite.jl index b0a81857b..af9ca2c10 100644 --- a/test/testsuite.jl +++ b/test/testsuite.jl @@ -15,6 +15,7 @@ include("compiler.jl") include("reflection.jl") include("examples.jl") include("convert.jl") +include("atomix_test.jl") function testsuite(backend, backend_str, backend_mod, AT, DAT) @testset "Unittests" begin @@ -69,6 +70,10 @@ function testsuite(backend, backend_str, backend_mod, AT, DAT) convert_testsuite(backend, AT) end + @testset "Atomix" begin + atomix_testsuite(backend, AT) + end + if backend_str == "CUDA" || backend_str == "ROCM" @testset "Examples" begin examples_testsuite(backend_str)