Collection Typeを使う重い計算にSwiftを使うにはまだ時期が早い?
アルゴリズムに専念できる「高級」言語でコンピュータ囲碁をやってみたいと思い、Swiftを選択してみました。
原始モンテカルロ碁を実装してみて、結論として、残念ながらSwift 2ではまだこういう計算は大変という結論を得ました。
以下、ボトルネックとなったところ。
// reference : Mr. Yamashita's sample code in lectures in Dentsu University let dir4 = [1, WIDTH, -1, -WIDTH] func count_liberty_sub(tz: Int, color: Int, inout liberty: Int, inout stone: Int) { ... for dir in dir4 { .... if board[z] == color { count_liberty_sub(z, color: color, liberty: &liberty, stone: &stone) } } }
このコードが重いのです。dir4はグローバルな定数ですが、関数count_liberty_subで使う時、Swiftは礼儀正しく、swift_bridgeObjectRetainを実行し、その中で_swift_retain_を実行します。
そして関数が戻る時には_swift_release_を実行。
このretainとreleaseがそれぞれ1-2msかかるので、他の処理にほとんど時間がかからなくても重い処理になります。
(試しにdir4に配列リテラルを直接描いてみたら、配列リテラルの生成とリリースが都度発生して悪化しました。)
グローバルな定数配列でARCをしても仕方ないと思うのですが、どういうものなのでしょう?
ちなみに、Optimization LevelはFast, Whole Module Optimizationです。
Swiftはベンチマークでいい数字出しているようですが、全体に、ArrayやSetなどCollection Typeを使うとまだスクリプト言語並みに重いという印象です。