平々毎々(アーカイブ)

はてなダイアリーのアーカイブです。

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

2つ前の私の記事で拾ってるツイートが全然関係ないものだったという指摘(すみません、申し訳ない)と、まともに計算できてないというバグの修正をしていただきました。ありがとうございました!

今回使ったのは System.Numerics.Vectors.Vector<T> でした。これはSIMDのビット長と型Tのビット長からいい感じに内部の配列長を決めてくれるもの……らしかったんですが、どうも、RyuJIT RTMでもやはりこのあたり(↓)がまずいらしく。

SIMD is only taking advantage of SSE2 hardware, currently. Due to some implementation restrictions, the RyuJIT CTP cannot automatically switch the size of the type based on local hardware capability. Full AVX support should arrive with a release of the .NET runtime that includes RyuJIT. We have prototyped this, but it just doesn’t work with our CTP deployment model.

http://blogs.msdn.com/b/dotnet/archive/2014/04/07/the-jit-finally-proposed-jit-and-simd-are-getting-married.aspx
System.Console.WriteLine("Vector<double>.Count=" + Vector<double>.Count);
System.Console.WriteLine("Vector<float>.Count=" + Vector<float>.Count);

の結果が

Vector<double>.Count=2
Vector<float>.Count=4

になってる(要は、128ビットと判定されてる)っていうのに気付いてない能天気なコード。いやこれはしょぼい。(エラーチェックちゃんとしろということでした)

(さらに追記)AVXのYMMレジスターは256ビットなのですが、ちゃんと256ビット演算をするにはお作法があるので、もしかしたらRyuJITがその作法にのっとってないのかもしれません。たとえば、AVXにもSIMD組み込み関数があるらしいのですが、それを使うと128 ビット演算になるとのことで、そういうコードになってるのかも。わかりませんが。

(さらにさらに追記)System.Numerics.Vector<T>をリフレクションでちょろちょろ見てみたら、一部のメソッドやプロパティには[JitIntrinsic]っていうinternalなカスタム属性がついてて、いちおうILも用意されてるけれども、たぶんここはハードウェアが適合する場合にJITSIMD関連のコードに置き換えるんだろうなと想像しました。で、Countプロパティにもその[JitIntrinsic]という属性がついてました。当然ですね。

あとでRyuJITのコードを覗いてみますね

(2016年5月にまた追記)自分のとこのCPUは Core i5-2410M だったのですが、これってつまりSandy Bridgeでして、Sandy Bridge世代でのAVX演算は(中略)128bitずつ2回に分けて演算を行なうという話があるので、128bit判定されたのは単にそれが理由かもしれません。つまり、Haswellアーキテクチャ以降なら256bit判定されるかも。いずれ試します。

結果は青子守唄さんのとこを見てほしいですが、期待したほどには速くならなかったよとのこと。

そうですねえ、青子守唄さんがご自身で書いている通り、メソッド呼び出しコストがあんまり無視できない状態ですね。単に計算すれば速いところをデリゲート経由にしてますから。引数がstructなんでコピーにも若干のコストがかかると思います。
そもそも、本当はVector4d (256ビット) が使えて、それで4次元数の掛け算でも足し算でもいっぺんにやったほうがいいのですが、現状128ビットだとそれもね。Vector4fで精度を落とすのはそれはそれで意味がない。

とりいそぎデリゲートをやめてみました。

https://github.com/matarillo/simd/tree/d443cdd92c40718ec9d1ff0084078e62829adb55

kenta@ASPIRE3830T C:\Users\kenta\Desktop\simd\cs\simd\bin\x64\Release
> .\simd
Normal: 4638 [ms]
Simd: 2927 [ms]

それでも倍にはならないですね。

(さらに追記)青子守唄さんも同じようにコードを書き換えて、メソッド呼び出しがなくなるようにした模様。(青子守唄さんの場合はVector<double>.Countの結果で丁寧に分岐して、それぞれ最適なコードが実行されるようにしてますが)

ちなみに自分のとこのCPUは前にも書いたのですが、SIMDに関係するところで言うと

kenta@ASPIRE3830T C:\Users\kenta
> \Binaries\SysinternalsSuite\Coreinfo.exe |grep -E "SSE|AVX"

Coreinfo v3.31 - Dump information on system CPU and memory topology
Copyright (C) 2008-2014 Mark Russinovich
Sysinternals - www.sysinternals.com
SSE             *       Supports Streaming SIMD Extensions
SSE2            *       Supports Streaming SIMD Extensions 2
SSE3            *       Supports Streaming SIMD Extensions 3
SSSE3           *       Supports Supplemental SIMD Extensions 3
SSE4a           -       Supports Streaming SIMDR Extensions 4a
SSE4.1          *       Supports Streaming SIMD Extensions 4.1
SSE4.2          *       Supports Streaming SIMD Extensions 4.2
AVX             *       Supports AVX intruction extensions

です。