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

iOSDCでSwiftのStringの文字の数え方について話します #iOSDC

f:id:taka1068:20190905101333p:plain

スケジュール

概要

SwiftのStringはUnicodeを正しく扱うことを非常に重視した設計になっています。そのおかげで、絵文字を含む文字列でも正しい文字数を計算してくれます。

一方で、Unicodeの複雑さに引きずられてしまい直感的な操作ができない時もあります。たとえば、 string[2] と書いても3番目の文字を取得することはできません。

さらに、Swift自体のProtocol Oriented Programming思想の影響からCollectionプロトコルによる型の制約も話をややこしくしています。

僕のトークではそんな複雑ところを解きほぐしていきます。

このトークで説明すること

  • StringとCharacterはUnicodeとどう関連しているのか
  • StringはなぜIntで添字アクセスできないのか
  • Stringはなぜ添字アクセスで要素を変更できないのか

stack overflowなんかを見てN番目の文字を取得する方法はわかったものの、なぜそんなAPIになっているかイマイチ納得できない方には是非来ていただきたいです。Unicodeの仕様や計算量まで掘り下げて解説します。

スライドからの抜粋です
f:id:taka1068:20190905102728j:plain
f:id:taka1068:20190905105017j:plain
f:id:taka1068:20190905103155j:plain
f:id:taka1068:20190905103302j:plain

関連リンク

僕の所属するフェンリルのブログでも僕の登壇を紹介してくれています。とくに弊社のボトルウォーターはおすすめですよ!

engineers.fenrir-inc.com