[swift-users] dispatch concurrent map: is this right?

Dave Abrahams dabrahams at apple.com
Sun Oct 30 23:36:14 CDT 2016


on Sun Oct 30 2016, Dave Abrahams <swift-users-AT-swift.org> wrote:

>> I quite like the API as an extension on Range. I think it would be a
>> nice addition to Dispatch (once we start allowing additive proposals):
>>
>> extension Range where Bound : Strideable, Bound.Stride : SignedInteger {
>>
>>   func concurrentMap<T>(_ transform: (Bound) -> T) -> [T] {
>>     let n        = numericCast(count) as Int
>>     let buffer = UnsafeMutablePointer<T>.allocate(capacity: n)
>>
>>     DispatchQueue.concurrentPerform(iterations: n) {
>>       (buffer + $0).initialize(to: transform(lowerBound + numericCast($0)))
>>     }
>>
>>     // Unfortunately, the buffer is copied when making it an Array<T>.
>>     defer { buffer.deallocate(capacity: n) }
>>     return Array(UnsafeMutableBufferPointer<T>(start: buffer, count: n))
>>   }
>> }
>>
>> extension Collection {
>>   func concurrentMap<T>(_ transform: (Iterator.Element)->T) -> [T] {
>>
>>     // ‘as Range’ because CountableRange is a collection, causing the function to be recursive.
>>     return ((0..<numericCast(count)) as Range).concurrentMap {
>>       transform(self[index(startIndex, offsetBy: numericCast($0))])
>>     }
>>   }
>> }
>
> I see the beauty in what you're doing here, but I don't see any
> advantage to it for users.  Now Range (which will be collapsed with
> CountableRange in Swift 4) will have two overloads of concurrentMap.  In
> general, avoidable overloads are bad for the user experience.

Oh, and I should add, a suite of parallel algorithms would be great, but
it should be implemented similarly to lazy, so instead of 

   x.concurrentMap { ... }.concurrentFilter { ... }

you'd write

   x.parallel.map { ... }.filter { ... }

Cheers,

-- 
-Dave



More information about the swift-users mailing list