Hatena::ブログ(Diary)

猫とC#について書くmatarilloの雑記 Twitter

2015年09月19日

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

| Re: OpenCLやる前にSIMD使い切れっていう幻想を含むブックマーク Re: OpenCLやる前にSIMD使い切れっていう幻想のブックマークコメント

注意:この記事コードにはバグがあってまともに動いてません。詳細はこの記事この記事を読んでください。



(C#は・・・まぁ、RyuJITが使えるようになればマシになるのかな)

OpenCLやる前にSIMD使い切れっていう幻想 - aokomoriuta's blog

青子守唄さんのC#コードはそもそもSIMDが有効になってないんですよね。

C#でのSIMDの利用方法 - yukobaのブログにもある通り、System.Numerics.VectorsをNuGetで落としてこないといけない。

なので、いまさらですが、.NET Framework 4.6のRyuJITでSIMDを試してみましたよ。

コードは(bitbucketでもいいのですが)GitHubに置いてあります。

リポジトリ
https://github.com/matarillo/simd/tree/39642fc623d8f6c841ac1f7c50e26a2fdcd90cd9
C#のコード
https://github.com/matarillo/simd/blob/39642fc623d8f6c841ac1f7c50e26a2fdcd90cd9/cs/simd/Simd.cs

環境

結果

kenta@ASPIRE3830T C:\Users\kenta\Desktop\simd\cs\simd\bin\x64\Release
> .\simd.exe
Normal: 4691 [ms]
SIMD: 1394 [ms]
Parallel SIMD: 1169 [ms]
Press Any key...

コードみるとわかりますが

Parallel.For(0, n, i =>
{
	var a = f[i] * rm;
	x[i] += v[i] * dt + a * tmp;
	v[i] += a * dt;
});

こんなんで4倍程度速くなるので、「C#でいいじゃん」という気にもなりますね。ああもちろんF#でもVB.NETでも同じような恩恵は得られますが。冒頭にも書きましたが、このコードにはバグがあったのでぜんぜんまともな結果を出せていません。

ちなみにWindowsマシンを持ってなくて、MacやLinuxのMonoを使って試してみたい人は、Mono.Simd名前空間の型を使うように修正してくださいね。RyuJITの取り込みはまだ作業中のはずなので。

追記

まあたしかに連チャンで実行するとキャッシュに乗りますね。その辺対処したコードを後で載せましょう。

とりいそぎ画像だけ

f:id:matarillo:20150919124037p:image

もしかしてだけど、jのループが消えてるのがレギュレーション違反って言ってるのかな。

たとえばこういうこと?

struct NaiveVector4
{
	public double X0;
	public double X1;
	public double X2;
	public double X3;

	public NaiveVector4(double x0, double x1, double x2, double x3)
	{
		this.X0 = x0;
		this.X1 = x1;
		this.X2 = x2;
		this.X3 = x3;
	}

	public static  NaiveVector4 operator *(NaiveVector4 l, double r)
	{
		return new NaiveVector4(l.X0 * r, l.X1 * r, l.X2 * r, l.X3 * r);
	}

	public static NaiveVector4 operator +(NaiveVector4 l, NaiveVector4 r)
	{
		return new NaiveVector4(l.X0 + r.X0, l.X1 + r.X1, l.X2 + r.X3, l.X3 + r.X3);
	}

	public double[] Data
	{
		get { return new[] { X0, X1, X2, X3 }; }
	}
}

余計遅くなったりするけど。

f:id:matarillo:20150919130255p:image

こんな風に。

レギュレーションはまあどうでもいいとして、元コードでどうやってキャッシュに乗らないようにしてたのかは知りたい。C/C++力がたりないので。(でも上みたいなエアツイートしかしてくれないんだったら本人の説明は期待できないな。っていうかもしこのあたりのツイートが自分宛だったとしたらただの的はずれですしね。)そんでもってご自身で128bit SIMD試してるけど、ますますレギュレーションって何かね?ですね。ツイートは関係なかったとのことでいいがかり申し訳ありませんでした。バグを修正した記事も書いていただきました