docs.unity3d.com
    目次を表示する/隠す

    ループのベクトル化

    Burst は、ループのベクトル化 を使用してコードのパフォーマンスを向上させます。この手法を使用すると、一度に 1 つの値ではなく、同時に複数の値がループ処理されるため、コードのパフォーマンスが加速します。以下はその例です。

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static unsafe void Bar([NoAlias] int* a, [NoAlias] int* b, int count)
    {
        for (var i = 0; i < count; i++)
        {
            a[i] += b[i];
        }
    }
    
    public static unsafe void Foo(int count)
    {
        var a = stackalloc int[count];
        var b = stackalloc int[count];
    
        Bar(a, b, count);
    }
    

    Burst は Bar 内のスカラーループをベクトル化したループに変換します。その後、一度に 1 つの値をループ処理する代わりに、同時に複数の値をループ処理するコードを生成します。これにより、より高速なコードが生成されます。

    以下は、上記 Bar 内のループの AVX2 用に Burst が生成する x64 アセンブリです。

    .LBB1_4:
        vmovdqu    ymm0, ymmword ptr [rdx + 4*rax]
        vmovdqu    ymm1, ymmword ptr [rdx + 4*rax + 32]
        vmovdqu    ymm2, ymmword ptr [rdx + 4*rax + 64]
        vmovdqu    ymm3, ymmword ptr [rdx + 4*rax + 96]
        vpaddd     ymm0, ymm0, ymmword ptr [rcx + 4*rax]
        vpaddd     ymm1, ymm1, ymmword ptr [rcx + 4*rax + 32]
        vpaddd     ymm2, ymm2, ymmword ptr [rcx + 4*rax + 64]
        vpaddd     ymm3, ymm3, ymmword ptr [rcx + 4*rax + 96]
        vmovdqu    ymmword ptr [rcx + 4*rax], ymm0
        vmovdqu    ymmword ptr [rcx + 4*rax + 32], ymm1
        vmovdqu    ymmword ptr [rcx + 4*rax + 64], ymm2
        vmovdqu    ymmword ptr [rcx + 4*rax + 96], ymm3
        add        rax, 32
        cmp        r8, rax
        jne        .LBB1_4
    

    Burst はループを展開して 4 つの vpaddd 命令にベクトル化しました。この命令では、ループを繰り返すごとに 8 回、合計 32 回の整数加算が行われます。

    ループベクトル化 intrinsic

    Burst には、ループベクトル化の想定を表す実験的な intrinsic として Loop.ExpectVectorized と Loop.ExpectNotVectorized が含まれています。これによって Burst はコンパイル時にループベクトル化を検証します。これは自動ベクトル化を中断するような状況で役に立ちます。例えば、以下のようにコードに分岐を導入するような場合です。

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static unsafe void Bar([NoAlias] int* a, [NoAlias] int* b, int count)
    {
        for (var i = 0; i < count; i++)
        {
            if (a[i] > b[i])
            {
                break;
            }
    
            a[i] += b[i];
        }
    }
    

    これによってアセンブリは以下のように変更されます。

    .LBB1_3:
        mov        r9d, dword ptr [rcx + 4*r10]
        mov        eax, dword ptr [rdx + 4*r10]
        cmp        r9d, eax
        jg        .LBB1_4
        add        eax, r9d
        mov        dword ptr [rcx + 4*r10], eax
        inc        r10
        cmp        r8, r10
        jne        .LBB1_3
    

    ループがスカラーであり、ループを繰り返すごとに 1 回の整数加算しかしないので、これは最適とは言えません。コード内のどこで行われているか特定しにくい可能性があるため、ループベクトル化の想定を表す実験的な intrinsic である Loop.ExpectVectorized と Loop.ExpectNotVectorized を使用します。これによって Burst はコンパイル時にループベクトル化を検証します。

    この intrinsic は実験的なものなので、有効にするには UNITY_BURST_EXPERIMENTAL_LOOP_INTRINSICS プリプロセッサ定義を使用する必要があります。

    以下の例は、元の Bar の例に Loop.ExpectVectorized intrinsic を使用したものを示しています。

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static unsafe void Bar([NoAlias] int* a, [NoAlias] int* b, int count)
    {
        for (var i = 0; i < count; i++)
        {
            Unity.Burst.CompilerServices.Loop.ExpectVectorized();
    
            a[i] += b[i];
        }
    }
    

    これで Burst はループがベクトル化されているかどうかをコンパイル時に検証します。ループがベクトル化されていない場合は、Burst でコンパイラーエラーが発生します。以下の例ではエラーが発生します。

    [MethodImpl(MethodImplOptions.NoInlining)]
    private static unsafe void Bar([NoAlias] int* a, [NoAlias] int* b, int count)
    {
        for (var i = 0; i < count; i++)
        {
            Unity.Burst.CompilerServices.Loop.ExpectVectorized();
    
            if (a[i] > b[i])
            {
                break;
            }
    
            a[i] += b[i];
        }
    }
    

    Burst ではコンパイル時に以下のエラーが発生します。

    LoopIntrinsics.cs(6,9): Burst error BC1321: The loop is not vectorized where it was expected that it is vectorized.

    Important

    これらの intrinsic は if ステートメント内では動作しません。Burst でこの現象を防ぐことはできないため、これに関するコンパイル時のエラーは発生しません。

    トップに戻る
    Copyright © 2023 Unity Technologies — 商標と利用規約
    • 法律関連
    • プライバシーポリシー
    • クッキー
    • 私の個人情報を販売または共有しない
    • Your Privacy Choices (Cookie Settings)