SIMD hızlandırılmış sayısal türleri kullanma

SIMD (Tek yönerge, birden çok veri), tek bir yönerge kullanarak birden çok veri parçası üzerinde paralel olarak bir işlem gerçekleştirmek için donanım desteği sağlar. .NET'te, ad alanı altında System.Numerics SIMD hızlandırılmış türler kümesi vardır. SIMD işlemleri donanım düzeyinde paralelleştirilebilir. Bu, matematiksel, bilimsel ve grafik uygulamalarında yaygın olarak kullanılan vektörleştirilmiş hesaplamaların aktarım hızını artırır.

.NET SIMD hızlandırılmış türler

.NET SIMD hızlandırılmış türleri aşağıdaki türleri içerir:

  • Vector22, 3 ve Vector4 4 Single değerleriyle vektörleri temsil eden , Vector3ve türleri.

  • 3x2 matrisini temsil eden ve Matrix4x44x4 değer matrisini Single temsil eden iki matris türüMatrix3x2.

  • Plane Değerleri kullanarak Single üç boyutlu alanda bir düzlemi temsil eden tür.

  • Değerleri Quaternion kullanarak Single üç boyutlu fiziksel döndürmeleri kodlamak için kullanılan vektörünü temsil eden tür.

  • Vector<T> Belirtilen sayısal türde bir vektöri temsil eden ve SIMD desteğinden yararlanan geniş bir işleç kümesi sağlayan tür. Bir Vector<T> örneğin sayısı bir uygulamanın ömrü boyunca sabittir, ancak değeri Vector<T>.Count kodu çalıştıran makinenin CPU'sunun değerine bağlıdır.

    Not

    Türü Vector<T> .NET Framework'e dahil değildir. Bu türe erişmek için System.Numerics.Vectors NuGet paketini yüklemeniz gerekir.

SIMD hızlandırmalı türler, SIMD hızlandırmalı olmayan donanımlarla veya JIT derleyicileriyle kullanılabilecek şekilde uygulanır. SIMD yönergelerinden yararlanmak için 64 bit uygulamalarınızın RyuJIT derleyicisini kullanan çalışma zamanı tarafından çalıştırılması gerekir. RyuJIT derleyicisi .NET Core ve .NET Framework 4.6 ve sonraki sürümlerde bulunur. SIMD desteği yalnızca 64 bit işlemciler hedeflendiğinde sağlanır.

SIMD nasıl kullanılır?

Özel SIMD algoritmalarını yürütmeden önce, konak makinenin bir döndüren Booleankullanarak Vector.IsHardwareAcceleratedSIMD'yi destekleip desteklemediğini denetlemek mümkündür. Bu, SIMD hızlandırmanın belirli bir tür için etkinleştirildiğini garanti etmez, ancak bazı türler tarafından desteklendiğinin bir göstergesidir.

Basit Vektörler

.NET'teki Vector2en ilkel SIMD hızlandırmalı türler, Vector32, 3 ve Vector4 4 Single değere sahip vektörleri temsil eden , ve türleridir. Aşağıdaki örnekte iki vektör eklemek için kullanılır Vector2 .

var v1 = new Vector2(0.1f, 0.2f);
var v2 = new Vector2(1.1f, 2.2f);
var vResult = v1 + v2;

.NET vektörlerini kullanarak , TransformClamp vb. gibi Dot productvektörlerin diğer matematiksel özelliklerini hesaplamak da mümkündür.

var v1 = new Vector2(0.1f, 0.2f);
var v2 = new Vector2(1.1f, 2.2f);
var vResult1 = Vector2.Dot(v1, v2);
var vResult2 = Vector2.Distance(v1, v2);
var vResult3 = Vector2.Clamp(v1, Vector2.Zero, Vector2.One);

Matris

Matrix3x2, 3x2 matrisi ve Matrix4x44x4 matrisi temsil eder. Matrisle ilgili hesaplamalar için kullanılabilir. Aşağıdaki örnekte, SIMD kullanılarak matrisin karşılık gelen transpose matrisine çarpması gösterilmektedir.

var m1 = new Matrix4x4(
            1.1f, 1.2f, 1.3f, 1.4f,
            2.1f, 2.2f, 3.3f, 4.4f,
            3.1f, 3.2f, 3.3f, 3.4f,
            4.1f, 4.2f, 4.3f, 4.4f);

var m2 = Matrix4x4.Transpose(m1);
var mResult = Matrix4x4.Multiply(m1, m2);

Vektör<T>

, Vector<T> daha uzun vektörler kullanma olanağı sağlar. Bir Vector<T> örneğin sayısı sabittir, ancak değeri Vector<T>.Count kodu çalıştıran makinenin CPU'sunun değerine bağlıdır.

Aşağıdaki örnekte kullanarak Vector<T>iki dizinin öğe başına toplamının nasıl hesaplanması gösterilmektedir.

double[] Sum(double[] left, double[] right)
{
    if (left is null)
    {
        throw new ArgumentNullException(nameof(left));
    }

    if (right is null)
    {
        throw new ArgumentNullException(nameof(right));
    }

    if (left.Length != right.Length)
    {
        throw new ArgumentException($"{nameof(left)} and {nameof(right)} are not the same length");
    }

    int length = left.Length;
    double[] result = new double[length];

    // Get the number of elements that can't be processed in the vector
    // NOTE: Vector<T>.Count is a JIT time constant and will get optimized accordingly
    int remaining = length % Vector<double>.Count;

    for (int i = 0; i < length - remaining; i += Vector<double>.Count)
    {
        var v1 = new Vector<double>(left, i);
        var v2 = new Vector<double>(right, i);
        (v1 + v2).CopyTo(result, i);
    }

    for (int i = length - remaining; i < length; i++)
    {
        result[i] = left[i] + right[i];
    }

    return result;
}

Açıklamalar

SIMD'nin bir performans sorununu kaldırma ve bir sonrakini kullanıma sunma olasılığı daha yüksektir, örneğin bellek aktarım hızı. Genel olarak SIMD kullanmanın performans avantajı belirli senaryoya bağlı olarak değişir ve bazı durumlarda simd olmayan daha basit eşdeğer koddan daha da kötü performans gösterebilir.