[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