Array copy primops
Johan Tibell
johan.tibell at gmail.com
Tue Jan 25 21:57:27 CET 2011
On Tue, Jan 25, 2011 at 9:47 PM, Roman Leshchinskiy <rl at cse.unsw.edu.au> wrote:
> On 25/01/2011, at 20:26, Johan Tibell wrote:
> 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 thought it did, but I might very well be misstaken. Perhaps Simon
could explain. Simon, is the GC allowed to run during "unsafe" foreign
calls? If no, should we be relying on this behavior?
>> 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.
Right, that only applies to Array#. I also agree we should avoid
unnecessary primops.
>
>> 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.
Using a cloneArray# primop I can avoid the issue altogether in my
particular case. If we had a portable memset_pattern we could perhaps
speed up 'newArray#' in general.
>>> 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?
I do want my cloneArray# to copy. I'm a bit confused however, did you
intend for both your cloneArray#, thawArray#, and freezeArray# to
copy? Put in another way, assuming that you start out with an Array#
that you want to update one element in and have another Array# in the
end, which sequence of primops (of the ones you defined) would you
use?
Johan
More information about the Cvs-ghc
mailing list