Array copy primops
Roman Leshchinskiy
rl at cse.unsw.edu.au
Tue Jan 25 21:47:40 CET 2011
On 25/01/2011, at 20:26, Johan Tibell wrote:
> On Tue, Jan 25, 2011 at 6:35 PM, Roman Leshchinskiy <rl at cse.unsw.edu.au> wrote:
>> Daniel Peebles wrote:
>>>
>>> Johan Tibell and I have been working on some new primops for GHC that
>>> would allow people to use fast optimized memcpys on unpinned memory.
>>
>> Why not just use memcpy?
>
> I'm working with unpinned memory so memcpy is not an option as the GC
> might move the memory during the foreign call.
AFAIK, the GC never runs during foreign calls. This, combine with the fact that GHC can pass ByteArray# directly to FFI calls, should make memcpy safe even for unpinned byte arrays. At least that's how I understand it.
> I also want to avoid to
> avoid filling the array twice (first with a initial element I don't
> care about, followed by the elements of another array).
That only applies to Array#, not ByteArray#, right? I fully agree that having block copy primops for the former is very worthwhile. I'm not sure we need primops for the latter.
> In addition, I'd like to avoid unnecessarily filling the arrays with a
> default element just to overwrite them right after. Speaking of array
> initialization, I'm not sure the CMM compiler is up to optimizing the
> initialization loop well either. My understanding is that the CMM
> compiler is not as strong as e.g. GCC when it comes to optimizing
> loops.
GHC doesn't optimise tight loops very well at the moment. The LLVM backend helps a bit here but not as much as it could because LLVM doesn't like the code that we generate very much.
>> It would be nice if those could be used on array slices. Maybe this:
>>
>> cloneArray# :: Array# a -> Int# -> Int# -> State# s -> Array# a
>> cloneMutableArray# :: MutableArray# s a -> Int# -> Int# -> State# s -> (#
>> State# s, MutableArray# s a #)
>> freezeArray# :: MutableArray# s a -> Int# -> Int# -> State# s -> (# State#
>> s, Array# a #)
>> thawArray# :: Array# a -> Int# -> Int# -> State# s -> (# State# s,
>> MutableArray# s a #)
>
> Supporting slicing would be nice. I'd prefer if we had e.g.
>
> cloneArray# :: Array# a -> Int# -> Int# -> State# s -> (# State# s
> MutableArray# s a #)
>
> as you might won't to mutate the clone array before freezing it. The
> use case I really want to support is updating a single array element,
> which would entail first cloning the array, the writing an element,
> and finally freezing the array.
>
>> Note that freezeArray# and thawArray# would be safe, i.e., would always
>> copy.
>
> That sounds awfully expensive!
I think your cloneArray# is the same as my thawArray#. I just tried to avoid having 4 different variants of clone. Or do you not want your cloneArray# to copy?
>>> cloneByteArray# :: ByteArray# -> State# s -> (# State s,
>>> MutableByteArray# s #)
>>> cloneMutableByteArray# :: MutableByteArray# s -> State# s -> (# State s,
>>> MutableByteArray# s #)
>>
>> Aren't these just newMutableByteArray# followed by copy? Why do you want
>> them to be primops? There shouldn't be any speed advantage.
>
> You're right (assuming that we don't zero the memory on allocation).
I don't think we do.
Roman
More information about the Cvs-ghc
mailing list