Skip to content

Index set ranges #291

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

Closed
wants to merge 4 commits into from
Closed

Index set ranges #291

wants to merge 4 commits into from

Conversation

Tokazama
Copy link
Member

@Tokazama Tokazama commented Jun 3, 2022

This is some ground work for supporting index types like those in Dex.

I've added two fields to OptionallyStaticUnitRange and OptionallyStaticStepRange that allow manually eliding bounds checks for the first and last values in a range. These fields are not intended to be used directly by most users. Rather, the goal is to have functions that correspond to similar syntax as those in Dex (i.., ..i, i<.., etc.), with a specific collection as a point of reference. I haven't yet decided what the actual method names should be to mirror this functionality. Perhaps something like, all_indices(A, >(i))? @AriMKatz, perhaps you have some ideas on this?

I've included benchmarks below just to demonstrate that this does provide the performance improvement you'd expect when skipping bounds checking. Providing formal methods for constructing these could also help avoid overuse and abuse of @inbounds.

axis = Base.OneTo(20)
ur = 1:10
ur_checked = ArrayInterface.OptionallyStaticUnitRange(1, 10, False(), False())
ur_partially_checked = ArrayInterface.OptionallyStaticUnitRange(1, 10, False(), True())
ur_unchecked = ArrayInterface.OptionallyStaticUnitRange(1, 10, True(), True())

sr = 1:2:9
sr_checked = ArrayInterface.OptionallyStaticStepRange(1, 2, 9, False(), False())
sr_partially_checked = ArrayInterface.OptionallyStaticStepRange(1, 2, 9, False(), True())
sr_unchecked = ArrayInterface.OptionallyStaticStepRange(1, 2, 9, True(), True())

julia> @benchmark checkindex(Bool, $axis, $ur)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  2.832 ns  17.912 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     3.093 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   3.158 ns ±  0.422 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

         █      ▁                               ▄▄            
  ▆▅▃▂▂▁▇█▇▂▂▁▁▅█▄▂▂▁▁▂▆▄▂▂▁▁▁▃▆▃▂▂▁▁▁▂▄▃▂▂▁▁▁▁▂██▆▂▂▂▁▁▂▃▅▃ ▃
  2.83 ns        Histogram: frequency by time        3.55 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark checkindex(Bool, $axis, $ur_checked)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  1.474 ns  17.443 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     1.644 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   1.644 ns ±  0.278 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

       ▁▁       ▅▃                                  ▁▁ ▂▇█▄   
  ▄▆▄▃▂██▅▄▆▇▅▄▆██▇▃▃▄▄▄▄▅▄▂▂▁▃▄▃▄▆▇▅▃▂▁▂▅▅▄▅▇█▅▃▂▂▂███████▇ ▄
  1.47 ns        Histogram: frequency by time        1.76 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark checkindex(Bool, $axis, $ur_partially_checked)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  2.545 ns  17.384 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     2.723 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   2.833 ns ±  0.454 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

         █       ▃                               ▅            
  ▃▆▂▁▁▁▃██▂▁▂▁▁▆█▄▂▁▁▁▂▂▂▁▁▁▁▁▂▅▂▁▁▁▁▁▂▄▃▁▁▁▁▁▁▄██▂▁▁▁▁▁▁▂▂ ▂
  2.54 ns        Histogram: frequency by time         3.2 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark checkindex(Bool, $axis, $ur_unchecked)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  2.824 ns  17.352 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     3.018 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   3.145 ns ±  0.387 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

         █▃                                    ▄              
  ▃▅▃▂▂▁▄██▄▂▂▂▄█▄▂▂▂▁▃▄▃▂▂▁▁▂▄▄▂▂▂▂▁▂▄▄▃▂▂▂▁▂▆██▃▂▂▂▁▂▂▃▃▂▂ ▃
  2.82 ns        Histogram: frequency by time        3.57 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark checkindex(Bool, $axis, $sr)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  3.193 ns  26.974 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     3.614 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   3.589 ns ±  0.550 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

  █▄ ▄▅  ▅▃  ▅▂  ▂▂   █▆   ▄▁    ▂▃▁  ▁                   ▁▃ ▂
  ██▄██▆▃██▄███▅▇██▁▆▆██▇▇▁██▅▃▁▁███▁▆█▇█▁▇█▄▁▁▆█▃▁▃▃▇▄▁▁▁██ █
  3.19 ns      Histogram: log(frequency) by time     4.74 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark checkindex(Bool, $axis, $sr_checked)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  1.477 ns  15.597 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     1.731 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   1.741 ns ±  0.323 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

      ▃                 █                                     
  ▃▂▂▄█▅▃▂▅▃▂▂▅▅▃▂▂▆▄▃▂▃██▄▃▂▆▄▄▆▂▂▂▃▃▂▂▂▂▃▂▁▁▁▃▃▂▁▁▂▇▄▂▂▁▁▃ ▃
  1.48 ns        Histogram: frequency by time        2.13 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark checkindex(Bool, $axis, $sr_partially_checked)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  2.616 ns  266.683 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     2.790 ns               ┊ GC (median):    0.00%
 Time  (mean ± σ):   2.900 ns ±   2.690 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

   █▁      ▁▆                                   ▇▇             
  ███▅▄▃▂▂▃███▇▄▂▂▂▃▄▄▃▃▂▂▂▂▃▄▃▃▃▂▂▁▁▃▅▅▃▃▂▂▂▁▁▅██▆▅▄▂▂▂▂▁▃▅▄ ▃
  2.62 ns         Histogram: frequency by time         3.2 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

julia> @benchmark checkindex(Bool, $axis, $sr_unchecked)
BenchmarkTools.Trial: 10000 samples with 1000 evaluations.
 Range (min  max):  2.904 ns  17.856 ns  ┊ GC (min  max): 0.00%  0.00%
 Time  (median):     3.206 ns              ┊ GC (median):    0.00%
 Time  (mean ± σ):   3.225 ns ±  0.429 ns  ┊ GC (mean ± σ):  0.00% ± 0.00%

   █      ▁▂                                   ▄▃         ▃   
  ██▆▃▂▂▁▂██▄▃▂▂▁▂▂▄▄▂▂▂▁▁▂▃▆▅▂▂▂▁▁▂▃▅▅▃▂▂▁▁▁▂▅██▄▂▂▂▁▁▂▃▆█▇ ▃
  2.9 ns         Histogram: frequency by time        3.55 ns <

 Memory estimate: 0 bytes, allocs estimate: 0.

@codecov
Copy link

codecov bot commented Jun 3, 2022

Codecov Report

Merging #291 (4fddcb1) into master (828ba3f) will decrease coverage by 0.80%.
The diff coverage is 70.45%.

@@            Coverage Diff             @@
##           master     #291      +/-   ##
==========================================
- Coverage   90.00%   89.20%   -0.81%     
==========================================
  Files           9        9              
  Lines        1301     1325      +24     
==========================================
+ Hits         1171     1182      +11     
- Misses        130      143      +13     
Impacted Files Coverage Δ
src/ranges.jl 88.34% <70.45%> (-5.13%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 828ba3f...4fddcb1. Read the comment docs.

@Tokazama
Copy link
Member Author

Integrating the bounds checking traits from #321 into index methods/types should be a lot less messy than this approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant