Skip to content

Conversation

@treeowl
Copy link
Contributor

@treeowl treeowl commented Jan 12, 2021

  • Make (!?) extract a value from the vector eagerly.
  • Make the range check for (!?) use one comparison instead of two.

* Make `(!?)` extract a value from the vector eagerly.
* Make the range check for `(!?)` use one comparison instead of two.
treeowl added a commit to treeowl/lens that referenced this pull request Jan 12, 2021
Use `!?` for vector `ix` rather than manual range calculations.
Once [this PR](haskell/vector#347) lands,
that will also make the lookups eager, as they should be.
v !? i | i < 0 || i >= length v = Nothing
| otherwise = Just $ unsafeIndex v i
-- Lengths are never negative, so we can check 0 <= i < length v
-- using one unsigned comparison.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment and logic. Is the idea that

fromIntegral (minBound :: Int) :: Word
9223372036854775808

is always bigger than any realistic length Vector could be?

I think that should explained more clearly, this is "too clever" otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@phadej, right; a vector of length over maxBound :: Int will break assumptions all over the place. I can add a comment to that effect.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Existing definition has a benefit of short-circuiting in compile time when i is a statically known negative number. But I do not think that this is an important scenario.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's probably worth adding note that fromIntegral (i :: Int) :: Word > fromIntegral (maxBound :: Int) :: Word for all negative Ints. Such optimization is not entirely obvious

@Shimuuar
Copy link
Contributor

(!) and indexM shoudl benefit from same optimization. Also are there any benchmarks that show benefit of this optimization?

@treeowl
Copy link
Contributor Author

treeowl commented Jan 14, 2021

(!) and indexM shoudl benefit from same optimization. Also are there any benchmarks that show benefit of this optimization?

No idea. The benefits will be pretty sensitive to branch prediction load, I imagine.

@Shimuuar
Copy link
Contributor

Even more importantly is to make sure that this change doesn't make things worse because GHC does something stupid with casts. Even more interesting target for such optimization is BOUNDS_CHECK macro. It's used everywhere

@Bodigrim
Copy link
Contributor

To be honest, I do not quite imagine(!?) in a tight, performance-sensitive loop, which randomly asks for elements inside and outside of the range. It's interesting to apply this optimization to BOUNDS_CHECK and try to benchmark / look at Core / look at assembly.

As always, the smallest PRs catch the biggest scrutiny :) Could the range check optimization be moved to a separate PR?

@Shimuuar
Copy link
Contributor

I looked at generated code for Word trick. Int->Word conversion is compiled to nothingness and less C-- code is generated. So I think it should be advantageous. I didn't try to run benchmarks yet

@Shimuuar Shimuuar mentioned this pull request Aug 11, 2021
@Bodigrim Bodigrim closed this in 8b4716b Aug 11, 2021
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.

4 participants