diff --git a/src/compiler/compilation.jl b/src/compiler/compilation.jl index 38eae18b..34706809 100644 --- a/src/compiler/compilation.jl +++ b/src/compiler/compilation.jl @@ -322,5 +322,18 @@ end # link the SPIR-V bytes into a session-local `ZeKernel` on the given context and device. function link_kernel(image::Vector{UInt8}, entry::String, ctx::ZeContext, dev::ZeDevice) mod = ZeModule(ctx, dev, image) - kernels(mod)[entry] + kernel = kernels(mod)[entry] + + # Kernels receive their arrays as `oneDeviceArray` structs, so to Level Zero every USM + # pointer they dereference is an indirect access. Without declaring that, the driver + # only maps the allocations we explicitly made resident, and a shared allocation that + # reuses the address of a freed (but never evicted) one isn't visible to the kernel: + # it reads zeros (JuliaGPU/oneAPI.jl#661). SYCL declares the same for all its kernels. + oneL0.indirect_access!( + kernel, oneL0.ZE_KERNEL_INDIRECT_ACCESS_FLAG_DEVICE | + oneL0.ZE_KERNEL_INDIRECT_ACCESS_FLAG_HOST | + oneL0.ZE_KERNEL_INDIRECT_ACCESS_FLAG_SHARED + ) + + return kernel end diff --git a/test/array.jl b/test/array.jl index 7d2f639c..5939e70c 100644 --- a/test/array.jl +++ b/test/array.jl @@ -118,6 +118,24 @@ end end end +# https://github.com/JuliaGPU/oneAPI.jl/issues/661: kernels have to declare indirect access, +# or an allocation that reuses the address of a freed one isn't visible to them. Whether a +# reused shared allocation reads as zeros depends on allocator state, so churn through +# enough allocations (two live ones, freed in alternating order, plus collections of the +# reductions' outputs) to hit it reliably. +@testset "reusing freed $B allocations" for B in (oneL0.DeviceBuffer, oneL0.SharedBuffer, oneL0.HostBuffer) + results = map(1:100) do i + a = oneArray{Float32, 1, B}(fill(1.0f0, 1024)) + b = oneArray{Float32, 1, B}(fill(2.0f0, 1024)) + r = (sum(a), maximum(b)) + oneAPI.unsafe_free!(isodd(i) ? a : b) + oneAPI.unsafe_free!(isodd(i) ? b : a) + i % 10 == 0 && GC.gc(false) + r + end + @test all(==((1024, 2)), results) +end + # https://github.com/JuliaGPU/CUDA.jl/issues/2191 @testset "preserving buffer types" begin a = oneVector{Int,oneL0.SharedBuffer}([1])