Skip to content
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

Hint to GHC that indices are to be used strictly #485

Merged
merged 4 commits into from
Mar 20, 2024
Merged

Conversation

Bodigrim
Copy link
Contributor

basicUnsafe{Read/Write/IndexM} are class members and, unless a call site was already specialised to a specific vector instance, GHC has no clue that the index is most certainly to be used eagerly. Bang before the index provides this vital for optimizer information.

I've been recently looking at Core for programs, where vectors did not specialise to a specific instance for one reason or another. It's really horrible: even if a specific instance remains unknown, we should tell GHC that passing boxed indices around is not OK.

Copy link
Contributor

@Shimuuar Shimuuar left a comment

Choose a reason for hiding this comment

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

Great find! I think slice/unsafeSlice would benefit from the same treatment as well.

P.S. Out of curiosity I looking into GHC's timing information. This change reduced allocation by simplifier by about 1e-3 when compiling unboxed vectors.

@@ -700,21 +700,25 @@ exchange v i x = checkIndex Bounds i (length v) $ unsafeExchange v i x
-- | Yield the element at the given position. No bounds checks are performed.
unsafeRead :: (PrimMonad m, MVector v a) => v (PrimState m) a -> Int -> m a
{-# INLINE unsafeRead #-}
unsafeRead v i = checkIndex Unsafe i (length v)
unsafeRead v !i = checkIndex Unsafe i (length v)
$ stToPrim

Choose a reason for hiding this comment

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

I 100% agree with this change, but unfortunately it means the following lines are no longer indented correctly with respect to the =. Is that something that can be fixed as part of this PR?


-- | Replace the element at the given position. No bounds checks are performed.
unsafeWrite :: (PrimMonad m, MVector v a) => v (PrimState m) a -> Int -> a -> m ()
{-# INLINE unsafeWrite #-}
unsafeWrite v i x = checkIndex Unsafe i (length v)
unsafeWrite v !i x = checkIndex Unsafe i (length v)
$ stToPrim

Choose a reason for hiding this comment

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

Same comment as above.

$ stToPrim
$ basicUnsafeWrite v i x

-- | Modify the element at the given position. No bounds checks are performed.
unsafeModify :: (PrimMonad m, MVector v a) => v (PrimState m) a -> (a -> a) -> Int -> m ()
{-# INLINE unsafeModify #-}
unsafeModify v f i = checkIndex Unsafe i (length v)
unsafeModify v f !i = checkIndex Unsafe i (length v)
$ stToPrim

Choose a reason for hiding this comment

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

Same comment as above.

@@ -725,7 +729,7 @@ unsafeModify v f i = checkIndex Unsafe i (length v)
-- @since 0.12.3.0
unsafeModifyM :: (PrimMonad m, MVector v a) => v (PrimState m) a -> (a -> m a) -> Int -> m ()
{-# INLINE unsafeModifyM #-}
unsafeModifyM v f i = checkIndex Unsafe i (length v)
unsafeModifyM v f !i = checkIndex Unsafe i (length v)
$ stToPrim . basicUnsafeWrite v i =<< f =<< stToPrim (basicUnsafeRead v i)

Choose a reason for hiding this comment

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

Same comment as above.

@Shimuuar
Copy link
Contributor

@Bodigrim I extended same treatment to unsafeSlice and converted comment to GHC note. This seems to be a good format for long form comment which are referenced from multiple places in source code

If you're fine with this I'd like to merge this PR

@Bodigrim
Copy link
Contributor Author

@Shimuuar sure, go ahead.

Bodigrim and others added 4 commits March 20, 2024 21:24
'basicUnsafe{Read/Write/IndexM}' are class members and, unless a call site was
already specialised to a specific vector instance, GHC has no clue that the index
is most certainly to be used eagerly. Bang before the index provides
this vital for optimizer information.
We have longish comment which is referenced from multiple places in source
code. GHC notes seems good option for that
@Shimuuar Shimuuar merged commit 655b5d6 into master Mar 20, 2024
22 checks passed
@Shimuuar Shimuuar deleted the indices-are-strict branch March 20, 2024 18:54
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.

None yet

3 participants