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