-1

値型構造体は、RAM ではなくプロセッサ キャッシュに存在するスタック ベースの変数です。そのため、値型変数を使用してプロセッサから RAM へのシステム バス経由のトリップを回避することで、参照型変数を使用するよりも高速になるはずです。stackallockそのため、 ( 「stackalloc」キーワードの実用的な使用)を行う代わりに、スタックベースの配列を表す次の構造を作成しました。

[StructLayout(LayoutKind.Sequential)]
public struct ArrayOf16Bytes
{
    public Byte e0;
    public Byte e1;
    public Byte e2;
    public Byte e3;
    public Byte e4;
    public Byte e5;
    public Byte e6;
    public Byte e7;
    public Byte e8;
    public Byte e9;
    public Byte eA;
    public Byte eB;
    public Byte eC;
    public Byte eD;
    public Byte eE;
    public Byte eF;

    public byte this[Int32 index] {
        get {
            switch (index) {
            case 0x0:
                return e0;
            case 0x1:
                return e1;
            case 0x2:   
                return e2;
            case 0x3:
                return e3;
            case 0x4:
                return e4;
            case 0x5:
                return e5;
            case 0x6:
                return e6;
            case 0x7:
                return e7;
            case 0x8:
                return e8;
            case 0x9:
                return e9;
            case 0xA:
                return eA;
            case 0xB:
                return eB;
            case 0xC:
                return eC;
            case 0xD:
                return eD;
            case 0xE:
                return eE;
            case 0xF:
                return eF;
            default:
                throw new IndexOutOfRangeException ();
            }
        }
        set {
            switch (index) {
            case 0x0:
                e0 = value;
                break;
            case 0x1:
                e1 = value;
                break;
            case 0x2:
                e2 = value;
                break;
            case 0x3:
                e3 = value;
                break;
            case 0x4:
                e4 = value;
                break;
            case 0x5:
                e5 = value;
                break;
            case 0x6:
                e6 = value;
                break;
            case 0x7:
                e7 = value;
                break;
            case 0x8:
                e8 = value;
                break;
            case 0x9:
                e9 = value;
                break;
            case 0xA:
                eA = value;
                break;
            case 0xB:
                eB = value;
                break;
            case 0xC:
                eC = value;
                break;
            case 0xD:
                eD = value;
                break;
            case 0xE:
                eE = value;
                break;
            case 0xF:
                eF = value;
                break;
            default:
                throw new IndexOutOfRangeException ();
            }
        }
    }
}

caseとは1 サイクルの命令であるjump tableため( C# で if/else と switch-case を使用する場合に大きな違いはありますか? )、コードの最初の部分は 2 番目のコードよりもはるかに高速である必要があります。cmpjump

次の例では、実際の配列よりも遅く動作します。

[Test]
public void TestStackArrayPerformance() {
    var random = new Xor128 ();

    byte[] x = new byte[16];

    ArrayOf16Bytes p = new ArrayOf16Bytes ();

    for (int i = 0; i < 16; i++) {
        x [i] = p [i] = random.As<IUniform<byte>> ().Evaluate ();
    }

    var index = random.As<IUniform<Int32>> ().Evaluate (0, 15);

    var timer = DateTime.Now;
    for (int i = 0; i < 1000000000; i++) {
        var t = x [i & 0xF];
        x [i & 0xF] = x [index];
        x [index] = t;
    }
    Console.WriteLine ("Spinup took: {0}", DateTime.Now - timer);

    timer = DateTime.Now;
    for (int i = 0; i < 1000000000; i++) {
        var t = x [i & 0xF];
        x [i & 0xF] = x [index];
        x [index] = t;
    }
    Console.WriteLine ("Operation 1 took: {0}", DateTime.Now - timer);


    timer = DateTime.Now;
    for (int i = 0; i < 100000000; i++) {
        var t = p [i & 0xF];
        p [i & 0xF] = p [index];
        p [index] = t;
    }
    Console.WriteLine ("Operation 2 took: {0}", DateTime.Now - timer);

}

私のマシンでは、このコードは次の結果を示しています。

Spinup took: 00:00:00.3005500
Operation 1 took: 00:00:00.2959800
Operation 2 took: 00:00:04.4344340
4

1 に答える 1