Skip to content

Commit ea463c1

Browse files
authored
Memory improvements (#395)
* Add an OutOfGPUMemoryError type with additional info. * Relax allocation limits.
1 parent aedfc12 commit ea463c1

File tree

3 files changed

+68
-19
lines changed

3 files changed

+68
-19
lines changed

lib/level-zero/memory.jl

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,24 @@ struct DeviceBuffer <: AbstractBuffer
4444
device::ZeDevice
4545
end
4646

47-
function device_alloc(ctx::ZeContext, dev::ZeDevice, bytesize::Integer, alignment::Integer=1;
48-
flags=0, ordinal::Integer=0)
49-
desc_ref = Ref(ze_device_mem_alloc_desc_t(; flags, ordinal))
50-
51-
ptr_ref = Ref{Ptr{Cvoid}}()
52-
zeMemAllocDevice(ctx, desc_ref, bytesize, alignment, dev, ptr_ref)
53-
54-
return DeviceBuffer(reinterpret(ZePtr{Cvoid}, ptr_ref[]), bytesize, ctx, dev)
47+
function device_alloc(ctx::ZeContext, dev::ZeDevice, bytesize::Integer,
48+
alignment::Integer=1; flags=0, ordinal::Integer=0)
49+
relaxed_allocation_ref = Ref(ze_relaxed_allocation_limits_exp_desc_t(;
50+
flags = ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE,
51+
))
52+
GC.@preserve relaxed_allocation_ref begin
53+
desc_ref = if bytesize > properties(dev).maxMemAllocSize
54+
pNext = Base.unsafe_convert(Ptr{Cvoid}, relaxed_allocation_ref)
55+
Ref(ze_device_mem_alloc_desc_t(; flags, ordinal, pNext))
56+
else
57+
Ref(ze_device_mem_alloc_desc_t(; flags, ordinal))
58+
end
59+
60+
ptr_ref = Ref{Ptr{Cvoid}}()
61+
zeMemAllocDevice(ctx, desc_ref, bytesize, alignment, dev, ptr_ref)
62+
63+
return DeviceBuffer(reinterpret(ZePtr{Cvoid}, ptr_ref[]), bytesize, ctx, dev)
64+
end
5565
end
5666

5767
Base.pointer(buf::DeviceBuffer) = buf.ptr
@@ -84,7 +94,8 @@ struct HostBuffer <: AbstractBuffer
8494
context::ZeContext
8595
end
8696

87-
function host_alloc(ctx::ZeContext, bytesize::Integer, alignment::Integer=1; flags=0)
97+
function host_alloc(ctx::ZeContext, bytesize::Integer, alignment::Integer=1;
98+
flags=0)
8899
desc_ref = Ref(ze_host_mem_alloc_desc_t(; flags))
89100

90101
ptr_ref = Ref{Ptr{Cvoid}}()
@@ -122,17 +133,27 @@ struct SharedBuffer <: AbstractBuffer
122133
device::Union{Nothing,ZeDevice}
123134
end
124135

125-
function shared_alloc(ctx::ZeContext, dev::Union{Nothing,ZeDevice}, bytesize::Integer,
126-
alignment::Integer=1; host_flags=0,
136+
function shared_alloc(ctx::ZeContext, dev::Union{Nothing,ZeDevice},
137+
bytesize::Integer, alignment::Integer=1; host_flags=0,
127138
device_flags=0, ordinal::Integer=0)
128-
device_desc_ref = Ref(ze_device_mem_alloc_desc_t(; flags=device_flags, ordinal))
129-
host_desc_ref = Ref(ze_host_mem_alloc_desc_t(; flags=host_flags))
130-
131-
ptr_ref = Ref{Ptr{Cvoid}}()
132-
zeMemAllocShared(ctx, device_desc_ref, host_desc_ref, bytesize, alignment,
133-
something(dev, C_NULL), ptr_ref)
134-
135-
return SharedBuffer(reinterpret(ZePtr{Cvoid}, ptr_ref[]), bytesize, ctx, dev)
139+
relaxed_allocation_ref = Ref(ze_relaxed_allocation_limits_exp_desc_t(;
140+
flags = ZE_RELAXED_ALLOCATION_LIMITS_EXP_FLAG_MAX_SIZE,
141+
))
142+
GC.@preserve relaxed_allocation_ref begin
143+
device_desc_ref = if dev !== nothing && bytesize > properties(dev).maxMemAllocSize
144+
pNext = Base.unsafe_convert(Ptr{Cvoid}, relaxed_allocation_ref)
145+
Ref(ze_device_mem_alloc_desc_t(; flags=device_flags, ordinal, pNext))
146+
else
147+
Ref(ze_device_mem_alloc_desc_t(; flags=device_flags, ordinal))
148+
end
149+
host_desc_ref = Ref(ze_host_mem_alloc_desc_t(; flags=host_flags))
150+
151+
ptr_ref = Ref{Ptr{Cvoid}}()
152+
zeMemAllocShared(ctx, device_desc_ref, host_desc_ref, bytesize, alignment,
153+
something(dev, C_NULL), ptr_ref)
154+
155+
return SharedBuffer(reinterpret(ZePtr{Cvoid}, ptr_ref[]), bytesize, ctx, dev)
156+
end
136157
end
137158

138159
Base.pointer(buf::SharedBuffer) = buf.ptr

lib/level-zero/oneL0.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ include("libze.jl")
2424
#
2525
# TODO: is it really required to (1) zero-initialize memory and (2) set the stype field?
2626
# none of these are documented...
27+
# TODO: add support for conveniently linking extension objects in pNext
2728
for (structure_type_enum, _) in CEnum.name_value_pairs(ze_structure_type_t)
2829
structure_type_name = string(structure_type_enum)
2930
@assert startswith(structure_type_name, "ZE_STRUCTURE_TYPE")

src/pool.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,30 @@
1+
"""
2+
OutOfGPUMemoryError()
3+
4+
An operation allocated too much GPU memory.
5+
"""
6+
struct OutOfGPUMemoryError <: Exception
7+
sz::Int
8+
dev::ZeDevice
9+
10+
function OutOfGPUMemoryError(sz::Integer=0, dev::ZeDevice=device())
11+
new(sz, dev)
12+
end
13+
end
14+
15+
function Base.showerror(io::IO, err::OutOfGPUMemoryError)
16+
print(io, "Out of GPU memory")
17+
if err.sz > 0
18+
print(io, " trying to allocate $(Base.format_bytes(err.sz))")
19+
end
20+
print(" on device $(properties(err.dev).name)")
21+
if length(memory_properties(err.dev)) == 1
22+
# XXX: how to handle multiple memories?
23+
print(" with $(Base.format_bytes(only(memory_properties(err.dev)).totalSize))")
24+
end
25+
return io
26+
end
27+
128
function allocate(::Type{oneL0.DeviceBuffer}, ctx, dev, bytes::Int, alignment::Int)
229
bytes == 0 && return oneL0.DeviceBuffer(ZE_NULL, bytes, ctx, dev)
330

0 commit comments

Comments
 (0)