SwiftでのConcurrent Map(並行処理map)の実装について

iOSDC Japan 2020 で「SwiftとGrand Central Dispatchによる並行アルゴリズム入門」というタイトルで登壇しました。 その中で、Concurrent Map(並行処理map)の実装について紹介しましたが、その補足を書きます。

fortee.jp

UnsafeMutableBufferPointerを使った実装

トークでは紹介しきれませんでしたが、UnsafeMutableBufferPointerを使う実装も可能です。 UnsafeMutableBufferPointerは、C言語と同等の扱いになるので、queue.syncで保護する必要はありません。

extension Array {
    func concurrentMap2<T>(_ transform: (Element) -> T) -> [T] {
        var result = ContiguousArray<T?>.init(repeating: nil, count: count)
        
        result.withUnsafeMutableBufferPointer { buffer in
            DispatchQueue.concurrentPerform(iterations: buffer.count) { index in
                buffer[index] = transform(self[index])
            }
        }
        return result.map { $0! }
    }
}

subscript でのgetについて

github.com

によると、subscriptでの get でも同時アクセスは良くないと読み取れます。

The most important consequence of this is that two different array elements cannot be simultaneously accessed.

ただ、サンプルコードでは特に問題なく動作していますし、

(like concurrently modifying different slices of an array)

を見ると、問題となるのはsetだけという気もしてきます。

このあたりについて情報がある人は教えていただけると幸いです。

参考

(discord/swift/2018/03/08/0) concurrentMapの実装について - moaible memo