はじめてのSIMD

MonoがSIMDに対応したので実験君。
SIMDについては→IT マネージャーおよび担当者向けリソース

私にSIMDは門外漢過ぎるのでhttp://cell.fixstars.com/pukiwiki/index.php?simd_0_lesson1から例題を拝借しました。(^^;

using Mono;
using Mono.Simd;
using System;
using System.Diagnostics;

public class Program
{
    public static void Main(string[] args)
    {
        const int LOOP=10000000;
        Vector4i vi = new Vector4i(1, 2, 3, 4);
        Vector4i vo = new Vector4i(0, 0, 0, 0);

        Stopwatch sw = new Stopwatch();
        sw.Start();
        for (int i = 0; i < LOOP; ++i) 
            vo += vi;
        Console.WriteLine ("{0},{1},{2},{3}", vo.X, vo.Y, vo.Z, vo.W);
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);
    }
}

// vim:set ts=4 sts=4 sw=4:

サンプルは単純にVector4を加算するだけのものです。これをsimd.csとか名前をつけて保存し、コンパイル

$ gmcs /r:Mono.Simd.dll simd.cs

では、実行してみます。まずは、SIMDをオフで。

$ mono -O=-simd simd.exe
10000000,20000000,30000000,40000000
1387

実行結果は1387msでした。

次に、SIMDをオンにします。(デフォルトがオン)

$ mono simd.exe
10000000,20000000,30000000,40000000
114

114ms。10倍以上高速化されています*1。実際のマシン語を見てみると、

  80:   0f 10 45 a8             movups -0x58(%ebp),%xmm0
  84:   0f 10 4d c8             movups -0x38(%ebp),%xmm1
  88:   66 0f fe c1             paddd  %xmm1,%xmm0
  8c:   0f 11 45 a8             movups %xmm0,-0x58(%ebp)
  90:   46                      inc    %esi

SSE命令であるmovupsが見つかりますね。

PDC2008のMonoセッションをでは、Monoがゲームに使われる例が紹介されていましたが、ゲームの動作環境としてのニーズが高まればこのような機能が望まれていくのでしょうね。本家MS.NETでも同様の機能を組み込んでくれるとうれしいのですが・・・

*1:もちろん、Mono.Simdを使ったSIMDを前提としたコードなので、SIMD無しに最適化したコードならここまで差はつかないと思います。