Skip to content

Commit

Permalink
wrap applyeager with plain_array
Browse files Browse the repository at this point in the history
it's more "eagerly" than contiguous
  • Loading branch information
johnnychen94 committed Jan 31, 2020
1 parent 84986a8 commit 551302e
Show file tree
Hide file tree
Showing 19 changed files with 144 additions and 136 deletions.
4 changes: 1 addition & 3 deletions src/operation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,7 @@ for FUN in (:applyeager, :applylazy, :applypermute,
end

function applyeager(op::Operation, img::AbstractArray, param)
# TODO: we don't need wrappers for eager mode, so we might want to
# add plain_array to it as well for the sake of simplicity
contiguous(applylazy(op, img, param))
plain_array(applylazy(op, img, param))
end

function applyaffineview(op::Operation, img::AbstractArray, param)
Expand Down
7 changes: 4 additions & 3 deletions src/operations/cache.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pl = ElasticDistortion(3,3) |> zeros(20,20) |> Rotate(-10:10)
"""
struct CacheImage <: ImageOperation end

applyeager(op::CacheImage, img::AbstractArray, param) = contiguous(img)
applyeager(op::CacheImage, img::AbstractArray, param) = plain_array(img)

function showconstruction(io::IO, op::CacheImage)
print(io, typeof(op).name.name, "()")
Expand Down Expand Up @@ -84,14 +84,15 @@ CacheImage(buffers::NTuple{N,AbstractArray}) where {N} = CacheImageInto(buffers)

@inline supports_lazy(::Type{<:CacheImageInto}) = true

applyeager(op::CacheImageInto, img::AbstractArray, param) = applylazy(op, img)
applyeager(op::CacheImageInto, img::Tuple) = applylazy(op, img)
applyeager(op::CacheImageInto, img::AbstractArray, param) = plain_array(applylazy(op, img))
applyeager(op::CacheImageInto, img::Tuple) = plain_array(applylazy(op, img))

function applylazy(op::CacheImageInto, img::Tuple)
throw(ArgumentError("Operation $(op) not compatiable with given image(s) ($(summary(img))). This can happen if the amount of images does not match the amount of buffers in the operation"))
end

function applylazy(op::CacheImageInto{<:AbstractArray}, img::AbstractArray, param)
# TODO: don't copy data if img is memory contiguous
copyto!(match_idx(op.buffer, axes(img)), img)
end

Expand Down
2 changes: 1 addition & 1 deletion src/operations/convert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ end
@inline supports_lazy(::Type{<:ConvertEltype}) = true

function applyeager(op::ConvertEltype{T}, img::AbstractArray, param) where T
contiguous(convert(AbstractArray{T}, img))
plain_array(convert(AbstractArray{T}, img))
end

function applylazy(op::ConvertEltype{T}, img::AbstractArray, param) where T
Expand Down
2 changes: 1 addition & 1 deletion src/operations/dims.jl
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ PermuteDims(perm::Vararg{Int,N}) where {N} = PermuteDims{N,perm,invperm(perm)}()
@inline supports_lazy(::Type{<:PermuteDims}) = true

function applyeager(op::PermuteDims{N,perm}, img::AbstractArray{T,N}, param) where {T,N,perm}
permutedims(img, perm)
plain_array(permutedims(img, perm))
end

function applylazy(op::PermuteDims{N,perm,iperm}, img::AbstractArray{T,N}, param) where {T,N,perm,iperm}
Expand Down
4 changes: 2 additions & 2 deletions src/operations/mapfun.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ end
@inline supports_lazy(::Type{<:MapFun}) = true

function applyeager(op::MapFun, img::AbstractArray, param)
contiguous(map(op.fun, img))
plain_array(map(op.fun, img))
end

function applylazy(op::MapFun, img::AbstractArray, param)
Expand Down Expand Up @@ -130,7 +130,7 @@ end

function applyeager(op::AggregateThenMapFun, img::AbstractArray, param)
agg = op.aggfun(img)
contiguous(map(x -> op.mapfun(x, agg), img))
plain_array(map(x -> op.mapfun(x, agg), img))
end

function applylazy(op::AggregateThenMapFun, img::AbstractArray, param)
Expand Down
2 changes: 1 addition & 1 deletion src/operations/noop.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct NoOp <: AffineOperation end

# TODO: implement method for n-dim arrays
toaffinemap(::NoOp, img::AbstractMatrix) = AffineMap(@SMatrix([1. 0; 0 1.]), @SVector([0.,0.]))
applyeager(::NoOp, img::AbstractArray, param) = contiguous(img)
applyeager(::NoOp, img::AbstractArray, param) = plain_array(img)
applylazy(::NoOp, img::AbstractArray, param) = img

function applyview(::NoOp, img::AbstractArray, param)
Expand Down
20 changes: 18 additions & 2 deletions src/utils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ Return a memory contiguous array for better performance.
Data copy only happens when necessary. For example, views returned by `view`,
`permuteddimsview` are such cases.
See also: [`plain_array`](@ref), [`plain_axes`](@ref)
"""
@inline contiguous(A::OffsetArray) = A
@inline contiguous(A::Array) = A
Expand All @@ -39,15 +41,29 @@ Data copy only happens when necessary. For example, views returned by `view`,
@inline _plain_array(A::SArray) = A
@inline _plain_array(A::MArray) = A
@inline _plain_array(A::Tuple) = map(_plain_array, A)
# avoid recursion
@inline plain_array(A) = _plain_array(contiguous(A))

"""
plain_array(A::AbstractArray)
plain_array(A::Tuple)
Return a memory contiguous plain array for better performance.
A plain array is either an `Array` or a `StaticArray`.
Data copy only happens when necessary. For example, views returned by `view`,
`permuteddimsview` are such cases.
See also: [`contiguous`](@ref), [`plain_axes`](@ref)
"""
@inline plain_array(A) = _plain_array(contiguous(A)) # avoid recursion

# --------------------------------------------------------------------

"""
plain_axes(A::AbstractArray)
Generate a 1-based array from `A` without data copy.
See also: [`contiguous`](@ref), [`plain_array`](@ref)
"""
@inline plain_axes(A::Array) = A
@inline plain_axes(A::OffsetArray) = parent(A)
Expand Down
18 changes: 10 additions & 8 deletions test/operations/tst_cache.jl
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,17 @@
# Identidy ranges
v = view(square, IdentityRange(1:3), IdentityRange(1:3))
img = @inferred Augmentor.applyeager(CacheImage(), v)
@test typeof(img) <: OffsetArray
@test typeof(img) <: Array
@test eltype(img) == eltype(v)
@test img == OffsetArray(square, 0, 0)
@test img !== square
@test img == square
# Affine
v = Augmentor.prepareaffine(square)
img = @inferred Augmentor.applyeager(CacheImage(), v)
@test typeof(img) <: OffsetArray
@test typeof(img) <: Array
@test eltype(img) == eltype(v)
@test img == OffsetArray(square, 0, 0)
@test img !== square
@test img == square
# Array and SubArray
v = view(square, :, :)
tmp,img = @inferred Augmentor.applyeager(CacheImage(), (square,v))
Expand All @@ -39,8 +41,8 @@
@test img == square
# OffsetArray
o = OffsetArray(square, (-1,2))
@test @inferred(Augmentor.applyeager(CacheImage(),o)) === o
@test @inferred(Augmentor.applyeager(CacheImage(),(o,square))) === (o,square)
@test @inferred(Augmentor.applyeager(CacheImage(),o)) === parent(o)
@test @inferred(Augmentor.applyeager(CacheImage(),(o,square))) === (parent(o),square)

@test Augmentor.supports_eager(CacheImage) === true
@test Augmentor.supports_lazy(CacheImage) === false
Expand Down Expand Up @@ -83,7 +85,7 @@ end
v = Augmentor.applylazy(Resize(2,3), camera)
res = @inferred Augmentor.applyeager(op, v)
@test res == v
@test typeof(res) <: OffsetArray
@test typeof(res) <: Array
@test parent(res) === op.buffer

res = @inferred Augmentor.applyeager(op, rect)
Expand Down Expand Up @@ -130,7 +132,7 @@ end
@test buf1 != square
@test buf2 != rgb_rect
@test res == (v1, v2)
@test typeof(res) <: NTuple{2,OffsetArray}
@test typeof(res) <: NTuple{2, Array}
@test parent.(res) === (op.buffer[1], op.buffer[2])

@test_throws BoundsError Augmentor.applyeager(op, (camera,buf1))
Expand Down
2 changes: 1 addition & 1 deletion test/operations/tst_channels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ end
@testset "special case that simplifies" begin
res = @inferred(Augmentor.applyeager(CombineChannels(Gray), reshape(channelview(Augmentor.prepareaffine(rect)), 1, 2, 3)))
@test collect(res) == rect
@test typeof(res) <: OffsetArray{Gray{N0f8}}
@test typeof(res) <: Array{Gray{N0f8}}
end
for (img_in, img_out) in imgs
res = @inferred(Augmentor.applyeager(CombineChannels(Gray), img_in))
Expand Down
33 changes: 16 additions & 17 deletions test/operations/tst_convert.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,26 @@
@testset "eager" begin
@test Augmentor.supports_eager(ConvertEltype) === true
@test Augmentor.supports_eager(ConvertEltype{Float64}) === true
res1 = convert(Array{Gray{Float32}}, rect)
res1a = OffsetArray(res1, 0, 0)
res1b = OffsetArray(res1, -2, -1)
img_out = convert(Array{Gray{Float32}}, rect)
imgs = [
(Float32, rect, Float32.(res1)),
(Float32, OffsetArray(rect, -2, -1), Float32.(res1b)),
(Gray{Float32}, rect, res1),
(Gray{Float32}, Float64.(rect), res1),
(Gray{Float32}, reshape(view(rect,:,:), 2,3), res1),
(Gray{Float32}, RGB{N0f8}.(rect), res1),
(Gray{Float32}, Augmentor.prepareaffine(rect), res1a),
(Gray{Float32}, OffsetArray(rect, -2, -1), res1b),
(Gray{Float32}, view(rect, IdentityRange(1:2), IdentityRange(1:3)), res1a),
(RGB{Float32}, rect, RGB{Float32}.(res1)),
(RGB{Float32}, OffsetArray(rect, -2, -1), RGB{Float32}.(res1b)),
(Float32, rect),
(Float32, OffsetArray(rect, -2, -1)),
(Gray{Float32}, rect),
(Gray{Float32}, Float64.(rect)),
(Gray{Float32}, reshape(view(rect,:,:), 2,3)),
(Gray{Float32}, RGB{N0f8}.(rect)),
(Gray{Float32}, Augmentor.prepareaffine(rect)),
(Gray{Float32}, OffsetArray(rect, -2, -1)),
(Gray{Float32}, view(rect, IdentityRange(1:2), IdentityRange(1:3))),
(RGB{Float32}, rect),
(RGB{Float32}, OffsetArray(rect, -2, -1))
]
@testset "single image" begin
for (T, img_in, img_out) in imgs
for (T, img_in) in imgs
res = @inferred(Augmentor.applyeager(ConvertEltype(T), img_in))
@test res img_out
@test typeof(res) == typeof(img_out)
out = T.(img_out)
@test res out
@test typeof(res) <: typeof(out)
end
end
end
Expand Down
32 changes: 16 additions & 16 deletions test/operations/tst_crop.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
for (img_in, inds) in imgs
res = @inferred(Augmentor.applyeager(Crop(1:2,2:3), img_in))
@test collect(res) == rect[1:2, 2:3]
@test axes(res) == inds
@test typeof(res) <: OffsetArray{eltype(img_in),2}
@test axes(res) == map(n->1:n, size(res)) # 1-base
@test typeof(res) <: Array{eltype(img_in),2}
end
end
@testset "multiple images" begin
Expand All @@ -41,7 +41,7 @@
inds = (inds1, inds2)
res = @inferred(Augmentor.applyeager(Crop(1:2,2:3), img_in))
@test collect.(res) == ntuple(i->rect[1:2, 2:3],2)
@test typeof(res) <: NTuple{2,OffsetArray{eltype(img_in1),2}}
@test typeof(res) <: NTuple{2,Array{eltype(img_in1),2}}
end
end
end
Expand Down Expand Up @@ -149,13 +149,13 @@ end
for (img_in, inds) in imgs
res = @inferred(Augmentor.applyeager(CropNative(inds), img_in))
@test collect(res) == rect[1:2, 2:3]
@test axes(res) == inds
@test typeof(res) <: OffsetArray{eltype(img_in),2}
@test axes(res) == map(n->1:n, size(res)) # 1-base
@test typeof(res) <: Array{eltype(img_in),2}
end
end
img = OffsetArray(rect, -2, -1)
@test collect(@inferred(Augmentor.applyeager(CropNative(-1:0,1:2), img))) == rect[1:2, 2:3]
@test typeof(Augmentor.applyeager(CropNative(-1:0,1:2), img)) <: OffsetArray
@test typeof(Augmentor.applyeager(CropNative(-1:0,1:2), img)) <: Array
end
@testset "affine" begin
@test Augmentor.supports_affine(CropNative) === false
Expand Down Expand Up @@ -278,8 +278,8 @@ end
for (img_in, inds) in imgs
res = @inferred(Augmentor.applyeager(CropSize(2,2), img_in))
@test collect(res) == img_in[inds...]
@test axes(res) == inds
@test typeof(res) <: OffsetArray{eltype(img_in),2}
@test axes(res) == map(n->1:n, size(res)) # 1-base
@test typeof(res) <: Array{eltype(img_in),2}
end
end
@testset "multiple images" begin
Expand All @@ -288,7 +288,7 @@ end
inds = (inds1, inds2)
res = @inferred(Augmentor.applyeager(CropSize(2,2), img_in))
@test collect.(res) == ntuple(i->img_in[i][inds[i]...],2)
@test typeof(res) <: NTuple{2,OffsetArray{eltype(img_in1),2}}
@test typeof(res) <: NTuple{2,Array{eltype(img_in1),2}}
end
end
end
Expand Down Expand Up @@ -417,8 +417,8 @@ end
for (img_in, inds) in imgs
res = @inferred(Augmentor.applyeager(CropRatio(1), img_in))
@test collect(res) == img_in[inds...]
@test axes(res) == inds
@test typeof(res) <: OffsetArray{eltype(img_in),2}
@test axes(res) == map(n->1:n, size(res)) # 1-base
@test typeof(res) <: Array{eltype(img_in),2}
end
end
@testset "multiple images" begin
Expand All @@ -427,7 +427,7 @@ end
inds = (inds1, inds2)
res = @inferred(Augmentor.applyeager(CropRatio(1), img_in))
@test collect.(res) == ntuple(i->img_in[i][inds[i]...],2)
@test typeof(res) <: NTuple{2,OffsetArray{eltype(img_in1),2}}
@test typeof(res) <: NTuple{2,Array{eltype(img_in1),2}}
end
end
end
Expand Down Expand Up @@ -553,8 +553,8 @@ end
for (img_in, inds) in imgs
res = @inferred(Augmentor.applyeager(RCropRatio(3/2), img_in))
@test collect(res) == img_in[inds...]
@test axes(res) == inds
@test typeof(res) <: OffsetArray{eltype(img_in),2}
@test axes(res) == map(n->1:n, size(res)) # 1-base
@test typeof(res) <: Array{eltype(img_in),2}
end
end
@testset "multiple images" begin
Expand All @@ -563,8 +563,8 @@ end
# make sure both images are processed
@test res1 == res2
@test axes(res1) == axes(res2)
@test typeof(res1) <: OffsetArray{Gray{N0f8}}
@test typeof(res2) <: OffsetArray{N0f8}
@test typeof(res1) <: Array{Gray{N0f8}}
@test typeof(res2) <: Array{N0f8}
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions test/operations/tst_dims.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
@testset "eager" begin
@test Augmentor.supports_eager(PermuteDims) === true
@test @inferred(Augmentor.supports_eager(typeof(PermuteDims(2,1)))) === true
f = (img) -> permutedims(img, (2,1))
f = (img) -> collect(permutedims(img, (2,1)))
imgs = [
(rect),
(Augmentor.prepareaffine(rect)),
Expand Down Expand Up @@ -74,7 +74,7 @@
@test_throws MethodError Augmentor.applylazy(PermuteDims(3,2,1), img_in)
res = @inferred(Augmentor.applylazy(PermuteDims(2,1), img_in))
@test res == img_out
@test res == Augmentor.applyeager(PermuteDims(2,1), img_in)
@test collect(res) == Augmentor.applyeager(PermuteDims(2,1), img_in)
@test typeof(res) == typeof(img_out)
end
end
Expand Down
Loading

0 comments on commit 551302e

Please sign in to comment.