On 24 Aug 2014, at 01:23, Jens Alfke <j...@mooseyard.com> wrote:

> 
>> On Aug 23, 2014, at 12:46 AM, Gerriet M. Denkmann <gerr...@mdenkmann.de> 
>> wrote:
> 
>> Works fine and is twice as fast.
> 
> That approach is a bit naive, as it's going to spawn a huge number of 
> [dispatched blocks] (something like O(n) of them, I think.) Also, once the 
> array sizes start getting smaller than a cache line the CPU cores are going 
> to be fighting over access to memory. That's probably why you got only a 2x 
> speedup instead of 4x or 8x (depending on your CPU).

My computer has 8 Cpus (4 of which are called "logical", so the other 4 clearly 
are "illogical", but they work quite fine nevertheless).

The actual implementation looks like:

quicksort( array, depth)
{
        partition( array )
        if ( depth < kLimit )
        {
                dispatch_apply(2...
                {
                        quicksort( left or right side, depth + 1)
                }
        }
        else
        {
                quicksort( left side, depth + 1)
                quicksort( right side, depth + 1)
        }
}

Depth starts with 0, so there are no more than 2^ kLimit dispatched blocks.

Messing around with kLimit shows: 
It gets faster up to kLimit = 3 or 4. I.e. 8 or 16 dispatched blocks.
The improvements by increasing kLimit are getting smaller.
Increasing kLimit even further than 4 makes it not faster.
Even tried kLimit = 1000 
Actual depths for an array of size 10 000 000 are about 54 ... 63; log2(10 mio) 
= 23.2, but the partition is not as good as theoretically possible - instead of 
halving the array, it partitions it into about 1/4 + 3/4 on average.


> 
>> But how to do this in Swift?
> 
> The same way as in Objective-C.

> 
>> Just doing the same as in Obj-C does not work (nor is it expected, as there 
>> is no documented thread-safeness of Swift arrays).
> 
> Well, Swift arrays are passed by value, not by reference. What does your 
> Swift implementation look like?

Using the "passed by value" thing in Swift, quicksort() would sort the array, 
but the caller wouldn't notice; it's array would remain unchanged, which is not 
really useful.

So I use:
func quicksortArray( inout array: [UInt32], lowerIndex: UInt, upperIndex: UInt, 
depth: UInt )

1. problem: 
Even with kLimit = 0 this gets really slow
Reason: the compiler notices that dispatch_apply is kind of dangerous and 
always copies the arrays to be used.
And copies them back into the containing array afterwards.

So I changed it to:

quicksort( array, depth)
{
        partition( array )
        if ( depth < kLimit )
        {
                dispatch_apply(2...
                {
                        quicksort( left or right side, depth + 1)
                }
        }
        else
        {
                quicksortWithoutDispatch( left side, depth + 1) // same as 
quicksort, but without any mention of dispatch_apply
                quicksortWithoutDispatch( right side, depth + 1)
        }
}

2. problem:
Sometimes (not always) one of the two arrays sorted inside of dispatch_apply is 
not copied back.

3. problem
Sometimes (not always) random crashes
Which kind of proves that dispatch_apply with Swift is not a very good idea.
Or (more likely): my way of doing it is not very clever.


Kind regards,

Gerriet.


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to