Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions src/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -880,8 +880,8 @@ Base.unsafe_convert(::Type{CuPtr{T}}, A::PermutedDimsArray) where {T} =
resize!(a::CuVector, n::Integer)

Resize `a` to contain `n` elements. If `n` is smaller than the current collection length,
the first `n` elements will be retained. If `n` is larger, the new elements are not
guaranteed to be initialized.
the first `n` elements will be retained. If `n` is larger, the new elements are initialized
with undefined values.
"""
function Base.resize!(A::CuVector{T}, n::Integer) where T
n == length(A) && return A
Expand Down Expand Up @@ -915,3 +915,38 @@ function Base.resize!(A::CuVector{T}, n::Integer) where T

A
end

# new version of resizing
function new_resize!(A::CuVector{T}, n::Integer) where T
n == length(A) && return A

# how to better choose the new size?
if n > length(A) || n < length(A) / 2
len = n > length(A) ? max(n, 2 * length(A)) : n

maxsize = len * aligned_sizeof(T)
bufsize = if isbitstype(T)
maxsize
else
# type tag array past the data
maxsize + len
end

new_data = context!(context(A)) do
mem = pool_alloc(memory_type(A), bufsize)
ptr = convert(CuPtr{T}, mem)
m = min(length(A), n)
if m > 0
GC.@preserve A unsafe_copyto!(ptr, pointer(A), m)
end
DataRef(pool_free, mem)
end
unsafe_free!(A)
A.data = new_data
A.maxsize = maxsize
A.offset = 0
end

A.dims = (n,)
A
end
57 changes: 57 additions & 0 deletions test/base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,63 @@ end
@test length(b) == 0
resize!(b, 1)
@test length(b) == 1

# new resizing
a = CuArray([1, 2, 3, 4, 5, 6])
CUDA.new_resize!(a, 6)
@test length(a) == 6
@test Array(a) == [1, 2, 3, 4, 5, 6]

CUDA.new_resize!(a, 5) # cut less than half
@test length(a) == 5
@test Array(a) == [1, 2, 3, 4, 5]
@test a.maxsize == 6 * sizeof(eltype(a))

CUDA.new_resize!(a, 2) # cut more than half
@test length(a) == 2
@test Array(a) == [1, 2]
@test a.maxsize == 2 * sizeof(eltype(a))

CUDA.new_resize!(a, 1) # cut to half
@test length(a) == 1
@test Array(a) == [1]
@test a.maxsize == 2 * sizeof(eltype(a))

CUDA.new_resize!(a, 2) # double the size
@test length(a) == 2
@test Array(a)[1:1] == [1]
@test a.maxsize == 2 * sizeof(eltype(a))

CUDA.new_resize!(a, 3) # add less than half
@test length(a) == 3
@test Array(a)[1:1] == [1]
@test a.maxsize == 4 * sizeof(eltype(a))

CUDA.new_resize!(a, 7) # add more than half
@test length(a) == 7
@test Array(a)[1:1] == [1]
@test a.maxsize == 7 * sizeof(eltype(a))

a = CuArray([1, 2])
# resizing an unsafe_wrapped array
b = unsafe_wrap(CuArray{Int}, pointer(a), 2)
CUDA.new_resize!(b, 3)
@test length(b) == 3
@test Array(b)[1:2] == [1, 2]
@test b.maxsize == 4 * sizeof(eltype(b))

# corner cases
b = CuArray{Int}(undef, 0)
@test length(b) == 0
CUDA.new_resize!(b, 1)
@test length(b) == 1
@test b.maxsize == 1 * sizeof(eltype(b))

b = CuArray{Int}(undef, 1)
@test length(b) == 1
CUDA.new_resize!(b, 0)
@test length(b) == 0
@test b.maxsize == 0 * sizeof(eltype(b))
end

@testset "aliasing" begin
Expand Down