1

I'm switching a program from using MVector Word32 to STUArray Word Word32. In my vector code, I used unsafeMove to move vector slices around; thinking it was probably wrapping memmove for efficiency.

case dst ⊕ 3 of
  src | n < src + w -> do
    let w0 = n - src
    let w' = w - w0
    unsafeMove (slice dst w0 v) (slice src w0 v)
    if w' <= 3
      then do
        unsafeMove (slice (n - 3) w' v) (slice 0 w' v)
      else do
        let w'' = w' - 3
        unsafeMove (slice (n - 3) 3 v) (slice 0 3 v)
        unsafeMove (slice 0 w'' v) (slice 3 w'' v)
  src | n < dst + w -> do
    let w1 = n - dst
    let w'' = w - w1
    unsafeMove (slice dst w1 v) (slice src w1 v)
    unsafeMove (slice 0 w'' v) (slice 3 w'' v)
  src -> do
    unsafeMove (slice dst w v) (slice src w v)

The MArray typeclass doesn't seem to expose a way to move multiple elements in a single call, only one-by-one. Is there a wrapper for moving multiple STUArray elements (or maybe ByteArray#) at once?

rampion
  • 87,131
  • 49
  • 199
  • 315

1 Answers1

5

thinking it was probably wrapping memmove for efficiency

First I decided to check for you whether this is actually true, and it is.

  • unsafeMove eventually boils down to the basicUnsafeCopy operation defined for MVector, which delegates to copyMutableArray.
  • copyMutableArray's implementation varies by GHC version. For old versions, it was just an IO loop in ordinary Haskell, but since 7.8 it has delegated to a primop copyMutableArray#.
  • copyMutableArray# is a wrapper around memmove and memcopy, depending whether the arrays overlap.

I grepped through the source of Data.Array, and found no references to copyMutableArray. Another possibility would be that Data.Array exposes some way for you to view your STUArray as a MutableArray, and thereby call copyMutableArray yourself. But I also find no mention of MutableArray in Data.Array.

My tentative conclusion is that there is no memmove/memcopy wrapper in Data.Array.

amalloy
  • 89,153
  • 8
  • 140
  • 205
  • 2
    It's not unusual to have to dig into `Data.Array.Base` or even `GHC.Arr` to actually get the access you need to perform reasonably efficient array operations. Unless you really need flexible indexing, use the arrays in `primitive` or perhaps `vector` instead. – dfeuer Dec 26 '20 at 06:39
  • 1
    @dfeuer aha, I'd somehow missed `Data.Vector.Unboxed` – rampion Dec 27 '20 at 15:27
  • @rampion, `vector` is very big. I haven't (yet) found modules there to let you opt out of the potentially expensive slicing machinery when you don't need it. And the mixed-mode fusion machinery is so complicated almost no one can understand what's going on under the hood or what they need to do to make sure their code is compiled as intended. – dfeuer Dec 27 '20 at 17:19