Here is a slightly modified version of your code that performs faster (this is even faster than the unsafe/pointer code) ...
static double FindMaxFastest(double[] x, int startIndex, int endIndex)
{
int i = startIndex;
double max = double.MinValue;
do
{
if (max < x[i])
max = x[i];
} while (i++ < endIndex);
return max;
}
You can try unsafe/pointer math in C# but it won't gain you the boost you expect. unsafe
can also even decrease performance as the compiler and runtime can't do some of its internal optimizations.
static unsafe double FixMaxFixed(double[] doubles, int startIndex, int endIndex)
{
var i = startIndex;
double max = double.MinValue;
fixed (double* p = doubles)
{
do
{
if (max < *(p + i))
max = *(p + i);
} while (i++ < endIndex);
}
return max;
}
... here is the test harness I used ...
static void Main()
{
var rnd = new Random();
var set = Enumerable.Range(0, 10000000).Select(i => rnd.NextDouble() * 100).ToArray();
var s = 50;
var e = 1000000;
var sw = new Stopwatch();
var r = new[] { new List<long>(), new List<long>(), new List<long>() };
for (var i = 0; i < 1000; i++)
{
sw.Restart();
FixMaxFixed(set, s, e);
sw.Stop();
r[0].Add(sw.ElapsedTicks);
sw.Restart();
FindMax(set, s, e);
sw.Stop();
r[1].Add(sw.ElapsedTicks);
sw.Restart();
FindMaxFastest(set, s, e);
sw.Stop();
r[2].Add(sw.ElapsedTicks);
}
//5721.785 6098.866 5432.225
Console.WriteLine(string.Join(" ", r.Select(i => i.Average())));
Console.Read();
}
... Using a Duff's device can really increase the performance (unrolling your loop) ...
(This runs in 50% of the time of my first example if the set is in descending order... 75% of the time if it is in ascending order)
static double FindMaxDuff(double[] x, int startIndex, int endIndex)
{
double max = x[startIndex];
switch ((endIndex - startIndex) % 10)
{
case 0:
if (max < x[startIndex++]) max = x[startIndex];
goto case 9;
case 9:
if (max < x[startIndex++]) max = x[startIndex];
goto case 8;
case 8:
if (max < x[startIndex++]) max = x[startIndex];
goto case 7;
case 7:
if (max < x[startIndex++]) max = x[startIndex];
goto case 6;
case 6:
if (max < x[startIndex++]) max = x[startIndex];
goto case 5;
case 5:
if (max < x[startIndex++]) max = x[startIndex];
goto case 4;
case 4:
if (max < x[startIndex++]) max = x[startIndex];
goto case 3;
case 3:
if (max < x[startIndex++]) max = x[startIndex];
goto case 2;
case 2:
if (max < x[startIndex++]) max = x[startIndex];
goto case 1;
case 1:
if (max < x[startIndex++]) max = x[startIndex];
break;
}
do
{
if (max < x[startIndex + 1]) max = x[startIndex + 1];
if (max < x[startIndex + 2]) max = x[startIndex + 2];
if (max < x[startIndex + 3]) max = x[startIndex + 3];
if (max < x[startIndex + 4]) max = x[startIndex + 4];
if (max < x[startIndex + 5]) max = x[startIndex + 5];
if (max < x[startIndex + 6]) max = x[startIndex + 6];
if (max < x[startIndex + 7]) max = x[startIndex + 7];
if (max < x[startIndex + 8]) max = x[startIndex + 8];
if (max < x[startIndex + 9]) max = x[startIndex + 9];
if (max < x[startIndex + 10]) max = x[startIndex + 10];
} while ((startIndex += 10) < endIndex);
return max;
}