-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: rework TileIterator #27
base: master
Are you sure you want to change the base?
Conversation
Codecov Report
@@ Coverage Diff @@
## master #27 +/- ##
==========================================
- Coverage 98.16% 96.91% -1.26%
==========================================
Files 2 5 +3
Lines 109 162 +53
==========================================
+ Hits 107 157 +50
- Misses 2 5 +3
Continue to review full report at Codecov.
|
I like that this exports So the plan would be to add more types of tiled unit ranges and a high level API for things like |
src/tile.jl
Outdated
### TiledIndices | ||
|
||
struct TiledIndices{N, T, R} <: AbstractArray{R, N} | ||
indices::NTuple{N, TiledUnitRange{T, R}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why restict to TiledUnitRange{T, R}
? Why not any AbstractVector
of ranges?
@jw3126 I think 52a8328 answers this. I borrowed the same relationship between julia> TileIndices((1:4, ), FixedTile((4, ))) == TileIterator((1:4, ), RelaxLastTile((4, )))
true
julia> TileIndices((1:4, ), (4, )) == TileIterator((1:4, ), (4, ))
true
julia> TileIndices((1:5,), 4, 2) == [(1:4,), (3:5,)]
true
julia> TileIndices((1:5,), 4) == [(1:4,), (5:5,)]
true
julia> TileIndices((1:5,), 4; keep_last=false) == [(1:4,)]
true Performance is also the same. (marginally better, actually) I haven't implemented The best, best thing I like about this PR is that it now supports all the indices semantics that https://docs.julialang.org/en/v1.5/manual/arrays/#man-supported-index-types describes: "An array of scalar indices". julia> FixedTileRange(CartesianIndices((2:10,)), 4)
3-element FixedTileRange{CartesianIndices{1, Tuple{UnitRange{Int64}}}, Int64, CartesianIndices{1, Tuple{UnitRange{Int64}}}}:
[CartesianIndex(2,), CartesianIndex(3,), CartesianIndex(4,), CartesianIndex(5,)]
[CartesianIndex(6,), CartesianIndex(7,), CartesianIndex(8,), CartesianIndex(9,)]
[CartesianIndex(10,)]
julia> FixedTileRange(collect(2:10), 4)
3-element FixedTileRange{Vector{Int64}, Int64, Vector{Int64}}:
[2, 3, 4, 5]
[6, 7, 8, 9]
[10] ping @timholy for a feedback |
```jldoctest; setup=:(using TiledIteration) | ||
julia> FixedTileRange(CartesianIndices((1:10, )), 4) | ||
3-element FixedTileRange{CartesianIndices{1,Tuple{UnitRange{Int64}}},Int64,CartesianIndices{1,Tuple{UnitRange{Int64}}}}: | ||
[CartesianIndex(1,), CartesianIndex(2,), CartesianIndex(3,), CartesianIndex(4,)] | ||
[CartesianIndex(5,), CartesianIndex(6,), CartesianIndex(7,), CartesianIndex(8,)] | ||
[CartesianIndex(9,), CartesianIndex(10,)] | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's even more ugly and unstable when it comes to N-d case.
julia> TileIndices(CartesianIndices((1:20, 1:20)), (7, 7))
3×3 TileIndices{Tuple{CartesianIndices{1, Tuple{UnitRange{Int64}}}, CartesianIndices{1, Tuple{UnitRange{Int64}}}}, 2, FixedTileRange{CartesianIndices{1, Tuple{UnitRange{Int64}}}, Int64, CartesianIndices{1, Tuple{UnitRange{Int64}}}}}:
CartesianIndex{2}[CartesianIndex(1, 1) CartesianIndex(1, 2) … CartesianIndex(1, 6) CartesianIndex(1, 7); CartesianIndex(2, 1) CartesianIndex(2, 2) … CartesianIndex(2, 6) CartesianIndex(2, 7); … ; CartesianIndex(6, 1) CartesianIndex(6, 2) … CartesianIndex(6, 6) CartesianIndex(6, 7); CartesianIndex(7, 1) CartesianIndex(7, 2) … CartesianIndex(7, 6) CartesianIndex(7, 7)] … CartesianIndex{2}[CartesianIndex(1, 15) CartesianIndex(1, 16) … CartesianIndex(1, 19) CartesianIndex(1, 20); CartesianIndex(2, 15) CartesianIndex(2, 16) … CartesianIndex(2, 19) CartesianIndex(2, 20); … ; CartesianIndex(6, 15) CartesianIndex(6, 16) … CartesianIndex(6, 19) CartesianIndex(6, 20); CartesianIndex(7, 15) CartesianIndex(7, 16) … CartesianIndex(7, 19) CartesianIndex(7, 20)]
CartesianIndex{2}[CartesianIndex(8, 1) CartesianIndex(8, 2) … CartesianIndex(8, 6) CartesianIndex(8, 7); CartesianIndex(9, 1) CartesianIndex(9, 2) … CartesianIndex(9, 6) CartesianIndex(9, 7); … ; CartesianIndex(13, 1) CartesianIndex(13, 2) … CartesianIndex(13, 6) CartesianIndex(13, 7); CartesianIndex(14, 1) CartesianIndex(14, 2) … CartesianIndex(14, 6) CartesianIndex(14, 7)] CartesianIndex{2}[CartesianIndex(8, 15) CartesianIndex(8, 16) … CartesianIndex(8, 19) CartesianIndex(8, 20); CartesianIndex(9, 15) CartesianIndex(9, 16) … CartesianIndex(9, 19) CartesianIndex(9, 20); … ; CartesianIndex(13, 15) CartesianIndex(13, 16) … CartesianIndex(13, 19) CartesianIndex(13, 20); CartesianIndex(14, 15) CartesianIndex(14, 16) … CartesianIndex(14, 19) CartesianIndex(14, 20)]
CartesianIndex{2}[CartesianIndex(15, 1) CartesianIndex(15, 2) … CartesianIndex(15, 6) CartesianIndex(15, 7); CartesianIndex(16, 1) CartesianIndex(16, 2) … CartesianIndex(16, 6) CartesianIndex(16, 7); … ; CartesianIndex(19, 1) CartesianIndex(19, 2) … CartesianIndex(19, 6) CartesianIndex(19, 7); CartesianIndex(20, 1) CartesianIndex(20, 2) … CartesianIndex(20, 6) CartesianIndex(20, 7)] CartesianIndex{2}[CartesianIndex(15, 15) CartesianIndex(15, 16) … CartesianIndex(15, 19) CartesianIndex(15, 20); CartesianIndex(16, 15) CartesianIndex(16, 16) … CartesianIndex(16, 19) CartesianIndex(16, 20); … ; CartesianIndex(19, 15) CartesianIndex(19, 16) … CartesianIndex(19, 19) CartesianIndex(19, 20); CartesianIndex(20, 15) CartesianIndex(20, 16) … CartesianIndex(20, 19) CartesianIndex(20, 20)]
and it simply crashes during the display if I use CartesianIndices((1:512, 1:512))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a way to display those CartesianIndices
as
[CartesianIndex(1, 1):CartesianIndex(1, 7), CartesianIndex(1, 1):CartesianIndex(8, 15), CartesianIndex(1, 1):CartesianIndex(16, 20)]
while still keep the current show behavior?
I vaguely remember that we have a top_level
keyword for display related function, but can't find the name of it now.
Tests pass for Julia>=1.1, efforts will be made to keep 1.0 compatibility (although I don't use it...) |
* oneunit for CartesianIndex * (:) method for CartesianIndex * IdentityUnitRange
Question: for RelaxStride with StepRange, what's the "correct" result? Case 1: julia> r = RoundedTileRange(1:2:9, 3)
3-element RoundedTileRange{StepRange{Int64, Int64}, Int64, StepRange{Int64, Int64}}:
1:2:5
3:2:7
5:2:9
julia> r = RoundedTileRange(1:2:9, 3)
3-element RoundedTileRange{StepRange{Int64, Int64}, Int64, StepRange{Int64, Int64}}:
1:2:5
3:2:7
4:2:8
julia> r = RoundedTileRange(1:2:9, 3)
2-element RoundedTileRange{StepRange{Int64, Int64}, Int64, StepRange{Int64, Int64}}:
1:2:5
5:2:9
# FixedTileRange
julia> r = FixedTileRange(1:2:9, 3)
2-element FixedTileRange{StepRange{Int64, Int64}, Int64, StepRange{Int64, Int64}}:
1:2:5
4:2:8 Case 2: julia> r = RoundedTileRange(1:2:9, 4)
3-element RoundedTileRange{StepRange{Int64, Int64}, Int64, StepRange{Int64, Int64}}:
1:2:7
2:2:8
3:2:9
julia> r = RoundedTileRange(1:2:9, 4)
2-element RoundedTileRange{StepRange{Int64, Int64}, Int64, StepRange{Int64, Int64}}:
1:2:7
3:2:9
# FixedTileRange
julia> r = FixedTileRange(1:2:9, 4)
2-element FixedTileRange{StepRange{Int64, Int64}, Int64, StepRange{Int64, Int64}}:
1:2:7
5:2:9 Seems to be the last one (as it has the same length to the FixedTileRange case)? |
I also favor the last one. Alternatively we could raise an error, in case of a non unit range. |
Possibly, but I'd like to give a solid support for all the valid indices type that Base defines. I could mark |
Sounds good! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This mostly looks good. I didn't investigate the "crash" but I wonder if it comes from type parameter issues?
`FixedTileRange(collect(1:10), 4)` creates a new `Vector` of length `4` everytime when | ||
`getindex` is called. | ||
""" | ||
struct FixedTileRange{R, T, RP} <: AbstractTileRange{R} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameters could use some clarificiation, maybe just by subtyping, e.g., R<:AbstractVector{<:Integer}
or something?
|
||
_eltype(::Type{R}) where R<:OrdinalRange = StepRange{eltype(R), eltype(R)} | ||
_eltype(::Type{R}) where R<:AbstractUnitRange = UnitRange{eltype(R)} | ||
_eltype(::Type{R}) where R<:AbstractVector = R # this includes CartesianIndices{1} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're standardizing OrdinalRange
and AbstractUnitRange
but allowing any other type of AbstractVector
? Does Vector{Int}
count?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, Vector{Int}
counts even though it is not memory-efficient. I choose to support that because Vector{Int}
is a valid indices type.
Supporting this enables us to pass lazy evaluated vectors, even though I'm not sure if there's practical usage right now. Currently, I'm mostly concerned about CartesianIndices and step range.
_fixedtile_length(r.indices[1], n, Δ, keep_last) | ||
end | ||
function _fixedtile_length(r::AbstractVector{T}, n, Δ, keep_last) where T<:Integer | ||
_fixedtile_length(UnitRange{T}(first(r), last(r)), n, Δ, keep_last) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe convert(UnitRange{T}, r)
just to make sure this is consistent with what is being passed in? Or are you intending to support r = 1:3:10
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, StepRange
and Vector{Int}
are designed to be supported.
julia> FixedTileRange(1:2:10, 2)
4-element FixedTileRange{StepRange{Int64,Int64},Int64,StepRange{Int64,Int64}}:
1:2:3
3:2:5
5:2:7
7:2:9
julia> FixedTileRange([2, 3, 4, 5, 6], 2)
3-element FixedTileRange{Array{Int64,1},Int64,Array{Int64,1}}:
[2, 3]
[4, 5]
[6]
I still need to figure out how this should be done for arbitrary vectors and step ranges; they're not working perfectly right now.
julia> FixedTileRange(collect(1:2:10), 2) # this is wrong
5-element FixedTileRange{Array{Int64,1},Int64,Array{Int64,1}}:
[1, 2]
[3, 4]
[5, 6]
[7, 8]
[9]
_length = _fixedtile_length(parent, n, Δ, keep_last) | ||
new{_eltype(R), T, R}(parent, n, Δ, keep_last, _length) | ||
end | ||
end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's interesting that this is conceptually equivalent to StepRange(1:5, BroadcastInt(2), 7:11)
(a range-of-ranges). Should we consider the FixedTileRange
in terms of the range
API?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, not sure if I understand it right, do you mean StepRange(1:5, BroadcastInt(2), 7:11)
is equivalent to
julia> TileIndices((1:5, 7:11), 2)
3×3 TileIndices{Tuple{UnitRange{Int64},UnitRange{Int64}},2,FixedTileRange{UnitRange{Int64},Int64,UnitRange{Int64}}}:
(1:2, 7:8) (1:2, 9:10) (1:2, 11:11)
(3:4, 7:8) (3:4, 9:10) (3:4, 11:11)
(5:5, 7:8) (5:5, 9:10) (5:5, 11:11)
? I couldn't find what BroadcastInt
is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we consider the
FixedTileRange
in terms of therange
API?
I would be largely relieved if we could separate the indices and tile indices world, just like how we are doing with normal array and fancy block arrays. If that's what you were thinking about.
or are you saying to could make something like FixedTileRange(start, stop; length, Δ, n)
only to mimic range
's usage? That would be a little bit hard because I do plan to support all indices types, including the vectors and CartesianIndices. Mimicking the range API won't improve the useability much IMO.
end | ||
|
||
Base.size(r::FixedTileRange) = (r.length, ) | ||
Base.length(r::FixedTileRange) = r.length |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need to define this (the fallbacks do it).
|
It's a bit hard to extend the current
TileIterator
's behavior, so here I plan to rework it here. The code design basically follows the same idea ofUnitRange
-CartesianIndices
.Improvements:
CartesianIndices
:TODO:
RelaxStride
tiling strategyTileIterator
cc: @jw3126
closes #24
closes #25
closes #26