using System;
using System.Collections.Concurrent;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Threading.Tasks;
namespace BenchApp
{
class Program
{
static void Main(string[] args)
{
double[] a = new double[16 * 1024 * 1024];
Random rnd = new Random(0);
for (int i = 0; i < a.Length; i++)
{
a[i] = rnd.NextDouble() * rnd.Next(1000);
}
var etalonSum = Enumerable.Sum(a);
var anothersum = a.Sum();
Console.WriteLine(etalonSum);
Console.WriteLine(anothersum);
}
}
public static class Test
{
[Pure]
public static double Sum(this double[] source)
{
if (source.Length < Constants.SingleThreadExecutionThreshold)
return Sum(source, 0, source.Length);
double result = 0;
object syncRoot = new object();
Parallel.ForEach(Partitioner.Create(0, source.Length),
() => (double)0,
(range, state, sum) => Sum(source, range.Item1, range.Item2),
x =>
{
lock (syncRoot)
result += x;
});
return result;
}
[Pure]
private static double Sum(this double[] source, int startIndex, int endIndex)
{
double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0;
checked
{
int i;
for (i = startIndex; i < endIndex - Constants.Step + 1; i += Constants.Step)
{
sum1 += source[i];
sum2 += source[i + 1];
sum3 += source[i + 2];
sum4 += source[i + 3];
}
if (i == source.Length)
return ((sum1 + sum2) + (sum3 + sum4));
if (i == source.Length - 1)
return ((sum1 + sum2) + (sum3 + sum4) + source[i]);
if (i == source.Length - 2)
return ((sum1 + sum2) + (sum3 + sum4) + (source[i] + source[i + 1]));
return ((sum1 + sum2) + (sum3 + sum4) + (source[i] + source[i + 1] + source[i + 2]));
}
}
internal static class Constants
{
public const int Step = 4;
public const int SingleThreadExecutionThreshold = 1024;
}
}
}