Reiner Pope
2017-11-17 05:37:51 UTC
Hi libraries@,
In GHC.Prim, it is documented that Array# and ArrayArray# have the same
runtime representation. I'd like to exploit this to put unlifted and lifted
pointers into the same array (for example, unlifted pointers at even
indices and lifted pointers at odd indices). The reason I want to do this
is to save some array header words, and also to improve the cache locality
of my data, so that a read of a (lifted, unlifted) pointer pair only needs
to touch a single cache line rather than two.
I believe it is safe to do this (put unlifted and lifted pointers in the
same array), as long as I always read at the same liftedness and type that
I ran the write at for that index. Can you confirm?
Specifically, I'm expecting to use a code pattern like the following, to
read an unlifted value from an Array#, by coercing the Array# to
ArrayArray#, then doing the unlifted read there:
coerceToArrayArray :: Array# a -> ArrayArray#
coerceToArrayArray = unsafeCoerce#
coerceToUnlifted :: forall (b :: TYPE 'UnliftedRep). ArrayArray# -> b
coerceToUnlifted = unsafeCoerce#
indexUnliftedFromArray ::
forall a (b :: TYPE 'UnliftedRep). Array# a -> Int# -> b
indexUnliftedFromArray arr i =
coerceToUnlifted (indexArrayArrayArray# (coerceToArrayArray arr) i)
Similarly, I'm expecting to do writes by coercing the array to a
MutableArrayArray# and doing the writes to that.
Reiner
In GHC.Prim, it is documented that Array# and ArrayArray# have the same
runtime representation. I'd like to exploit this to put unlifted and lifted
pointers into the same array (for example, unlifted pointers at even
indices and lifted pointers at odd indices). The reason I want to do this
is to save some array header words, and also to improve the cache locality
of my data, so that a read of a (lifted, unlifted) pointer pair only needs
to touch a single cache line rather than two.
I believe it is safe to do this (put unlifted and lifted pointers in the
same array), as long as I always read at the same liftedness and type that
I ran the write at for that index. Can you confirm?
Specifically, I'm expecting to use a code pattern like the following, to
read an unlifted value from an Array#, by coercing the Array# to
ArrayArray#, then doing the unlifted read there:
coerceToArrayArray :: Array# a -> ArrayArray#
coerceToArrayArray = unsafeCoerce#
coerceToUnlifted :: forall (b :: TYPE 'UnliftedRep). ArrayArray# -> b
coerceToUnlifted = unsafeCoerce#
indexUnliftedFromArray ::
forall a (b :: TYPE 'UnliftedRep). Array# a -> Int# -> b
indexUnliftedFromArray arr i =
coerceToUnlifted (indexArrayArrayArray# (coerceToArrayArray arr) i)
Similarly, I'm expecting to do writes by coercing the array to a
MutableArrayArray# and doing the writes to that.
Reiner