#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 |