aokomoriuta's blog

青子守歌のブログ

Re: Re: OpenCLやる前にSIMD使い切れっていう幻想

d.hatena.ne.jp

なんだか知らない間にぜんっぜん関係ないtweetを拾われて勝手に憤られてた上に、全然まともに計算していないもの*1を出されてたので、ちゃんと動くようにして測りなおしました。

計算機は前回と同じものを使いますが、手元からVS2013がなくなってVS2015になってしまったので、Visual Studioのバージョンだけ違います(System.Numerics.Vectorsが必要ですが、4.1.0を使ってます)。
結果は以下の通り。

  • C#(なにもしない)
    • 5.5秒ぐらい
  • C#(System.Numerics.Vector<double>)
    • 4.5秒ぐらい

ということで、1秒ぐらい縮まりました。

FX-8350だとSIMD幅が128bitと判定されてSystem.Numerics.Vector<double>.Countが2になっていました(※先の記事の通りAVX2を使えば256bitできます)。
なので、2倍弱ぐらいは期待したのですが、結果は1.2倍で、ちょっと微妙な感じです。
関数呼び出しのコストがこんなに取られてるのか・・・よく分かりません。

私は最近まともなC#を書けてないので、まともなC#erさんに解明を期待します。

追記 (09/21 11:30)

すいません、昨日眠い状態でコード書いてたので、最後にコミットせずにpushして安心して寝てしまってました・・・。多分昨日の時点ではSystem.Numerics.Vector<double>を使っても全然速くないどころか遅かったと思います。
正しいのはさっきコミットしました。これで、4.5秒ぐらい(x1.2ぐらい)です。

追記 (09/21 12:30)

構造体もちゃんとサイズを切り分けたら、速くなりました。

  • C#(なにもしない)
    • 5.5秒ぐらい
  • C#(System.Numerics.Vector<double>)
    • 2.5秒ぐらい

なぜか2倍以上出ている・・・?まぁとりあえず速くなったので良しとします。
多分これが一番早いと思います(フラグ)。

追記 (09/21 23:00)

という話を聞いて、確かに手元のSurface Pro 3(OS:Win10、CPU:i3 4020Y)で試したところ、256bit SIMDになってくれました。

  • C#(なにもしない)
    • 5.5秒ぐらい
  • C#(System.Numerics.Vector<double>)
    • 2.2秒ぐらい

CPUが違うので単純比較できませんが・・・。
実行可能ファイルも置いておくので、もしお時間のある方は、OSとCPUの情報を添えて、実行時間とSIMD長を教えてくれると嬉しいです。

追記 (10/17 15:00)

↓のコメントにある通りAkio Takahashiさんからpull requestもらってました。
全部は取り込みませんでしたが、一部を取り込んだところ、以下のようになりました。

  • C#(なにもしない)
    • 5.5秒ぐらい
  • C#(System.Numerics.Vector<double>)
    • 2.5秒ぐらい
  • C#(今回)
    • 1.3秒ぐらい

以前の記事C++SIMD(AVX2)が1.3秒ぐらいだったので、同等ぐらいには速くなったようです。
ちょっと使い方に工夫が要るのかもしれませんが、C++と同じぐらいの性能がでるのであれば、C#には

  • アライン考えなくていい
  • CPUに合わせて勝手にSIMD長変えてくれる(逆にこれは欠点でもある?)
  • 最初から演算子オーバーロードされてるのでintrinsic書かなくていい

という長所が3点あります。

積極的に使えるタイミングでは使っていきたいところですね。

*1:4倍近く加速されたとのことでしたが、System.Numerics.Vector<T>が何かをちゃんと理解できておらず、System.Numerics.Vector.Countを一切考慮できていない、結果的に半分しか計算できていない粗末なものだった(例えばxSimd[0][2]とかアクセスしたら、SIMD長が足りなくて例外吐いて死ぬ)