overlapping array copy strikes again!
Vladimir Panteleev
thecybershadow at gmail.com
Sun Jan 7 04:10:21 PST 2007
Dear Newsgroup and Mr. Bright,
I would like to once again bring to your attention the issue of
overlapping array copies.
I shall not start it from scratch, since we all know it has been discussed
before. Thus, I would like to build upon the following post by Mr. Bright:
http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=12818
To recap:
Currently, overlapping checks are only done in the debug (non-release)
version: the compiler uses _d_arraycopy from phobos/internal/arraycat.d.
This function already checks whether the copy would overlap, so in case
overlapped copy would get implemented, no performance loss would manifest
in the debug version (in fact it can be optimized, see below).
And what of the release code? In release mode, the compiler inlines a "rep
movsb" (why not movsd btw? it doesn't add a movsd even if the array
elements are 4 bytes long) to copy the array. Thus, any overlapping copy
would silently fail if the source's start address is before the
destination's.
Now, I would like to quote part of a post by Mr. Bright from 2004, which
finished off a thread on the same topic:
>> But I don't understand,
>> can't you first check if there is an overlap and then use the optimized
>> code or not depending on that?
>
> Yes, that can work. But since overlapping copies are relatively rare,
> it's
> fairly expensive.
>
>> From my point of view it seems very simple to do.
>> How many clock cycles takes to check for the overlap?
>
> 4 fetches, 2 adds, 2 compares, and register pressure. A lot of benchmarks
> tend to focus on these kinds of things, and D can't afford to get a
> reputation for being slow.
In reality, you don't need the 2 fetches, 2 adds and 1 compare. All that's
needed is 2 fetches (array start positions, which will be used for the
string operation anyway) and 1 compare. All that's needed to do is to
compare the starting positions, and set the string direction bit
appropriately (using std/cld). That is, unless there is more than meets
the eye (or met my eye, to the least).
Personally, I find overlapping copies an immutable part of the language.
It's not so rare when someone needs to delete a character or two from a
string (without concatenating slices, which creates redundant copies) - or
create a rotating queue (for example, event history which holds only the
last N events). Not being able to use them at all is quite an
inconvenience - the user has to resort to making extra copies.
Even if this one compare/flag set is unacceptable out of performance
reasons, would it be acceptable to let the compiler determine at compile
time when the user is trying to copy a slice of an array to another
position within the same array? I mean, statements like array[a..b] =
array[c..d]; - because I believe most situations where overlapping array
copy is necessary is when a slice of an array is copied over another slice
of the same array, AND in many cases when a slice of an array is copied
over another slice of the same array the user is trying to perform an
overlapping array copy.
Thank you for your attention.
--
Best regards,
Vladimir mailto:thecybershadow at gmail.com
More information about the Digitalmars-d
mailing list