Почему я использую встроенный API медленнее, чем наивное решение?

#c# #.net-core

Вопрос:

Я изо всех сил пытаюсь понять, почему мое использование встроенного API медленнее, чем просто суммирование с циклом foreach?

 public class ArraySum
{
    private double[] data;

    public ArraySum()
    {
        if (!Avx.IsSupported)
        {
            throw new Exception("Avx is not supported");
        }

        var rnd = new Random();

        var list = new List<double>();

        for (int i = 0; i < 100_000; i  )
        {
            list.Add(rnd.Next(500));
        }

        data = list.ToArray();
    }

    [Benchmark]
    public void Native()
    {
        int result = 0;
        foreach (int i in data)
        {
            result  = i;
        }

        Console.WriteLine($"Native: {result}");
    }

    [Benchmark]
    public unsafe void Intrinsics()
    {
        int vectorSize = 256 / 8 / 4;
        var accVector = Vector256<double>.Zero;
        int i;
        var array = data;
        fixed (double* ptr = array)
        {
            for (i = 0; i <= array.Length - vectorSize; i  = vectorSize)
            {
                var v = Avx.LoadVector256(ptr   i);
                accVector = Avx.Add(accVector, v);
            }
        }
        double result = 0;
        var temp = stackalloc double[vectorSize];
        Avx.Store(temp, accVector);
        for (int j = 0; j < vectorSize; j  )
        {
            result  = temp[j];
        }
        for (; i < array.Length; i  )
        {
            result  = array[i];
        }

        Console.WriteLine($"Intrinsics: {result}");
    }
 

Результат:

.NET SDK=6.0.100-rc.2.21505.57

 |     Method |     Mean |    Error |   StdDev |   Median |
|----------- |---------:|---------:|---------:|---------:|
|     Native | 387.6 us | 12.15 us | 35.83 us | 405.8 us |
| Intrinsics | 393.2 us |  9.01 us | 25.70 us | 385.0 us |
 

что может быть причиной этого?

Он работает на Windows и процессоре Intel Core i5-3340M с частотой 2,70 ГГц (Ivy Bridge), если это имеет значение

BenchmarkDotNet предупреждает, что ArraySum.Родной: По умолчанию -> Похоже, что распределение является бимодальным (mValue = 3,92)

Комментарии:

1. @bolov ты прав, я только что понял, что консоль работает очень медленно 😛 в любом случае спасибо

2. что бы это ни было, оно даже не считается правильно по какой-то причине для больших массивов

Ответ №1:

Я только что понял, что

собственный метод должен выполнять это на double s не int s, opsie

 [Benchmark]
public void Native()
{
    double result = 0;
    foreach (double i in data)
    {
        result  = i;
    }

    Console.WriteLine($"Native: {result}");
}



|     Method |     Mean |    Error |   StdDev |   Median |
|----------- |---------:|---------:|---------:|---------:|
|     Native | 415.1 us | 25.35 us | 73.95 us | 385.9 us |
| Intrinsics | 388.7 us |  7.58 us | 21.74 us | 384.7 us |
 

но также:

Console.WriteLine добавляет, вероятно, слишком много накладных расходов, которые намного превышают время, затраченное на выполнение sum, и искажает результаты

теперь разница более существенна:

 [Benchmark]
public double Native()
{
    double result = 0;
    foreach (double i in data)
    {
        result  = i;
    }

    return resu<
}

[Benchmark]
public unsafe double Intrinsics()
{
    int vectorSize = 256 / 8 / 4;
    var accVector = Vector256<double>.Zero;
    int i;
    var array = data;
    fixed (double* ptr = array)
    {
        for (i = 0; i <= array.Length - vectorSize; i  = vectorSize)
        {
            var v = Avx.LoadVector256(ptr   i);
            accVector = Avx.Add(accVector, v);
        }
    }
    double result = 0;
    var temp = stackalloc double[vectorSize];
    Avx.Store(temp, accVector);
    for (int j = 0; j < vectorSize; j  )
    {
        result  = temp[j];
    }
    for (; i < array.Length; i  )
    {
        result  = array[i];
    }

    return resu<
}




|     Method |     Mean |    Error |   StdDev |
|----------- |---------:|---------:|---------:|
|     Native | 92.92 us | 1.547 us | 1.447 us |
| Intrinsics | 25.06 us | 0.459 us | 1.090 us |