| ProfileManolo's HPC BlogBlogLists | Help |
|
|
August 08 Comparing the speed of array assumptions.Dealing with arrays is not as trivial as the commodity .NET developer thinks. The assumption of all elements from a array is a practical computation in HPC applications. So a Microsoft Student Partner told me that in C# the best way to allocate and sum the array is the jagged way. But why? He could not give me an answer. I searched the Internet and found an article on the MSDN about FxCop (A tool to analyze managed assemblies). The tool shows some kind of warnings if you are a stupid programmer. So one warning is: “Prefer jagged arrays over multidimensional”. Okay, Microsoft choice seems to be “jagged arrays”. I remember my first HPC lecture at the University where the lecturer told me that jagged arrays are potentially slow. An option to speed up the array operations is to use linear arrays. Comparing the speed of the different arrays would be helpful to argument in this discussion. First let me introduce the sample benchmark code. First the preferred array will be initialized with the value 0.01 for each element. Next a sum of the whole array is computed p-times. In pseudo code: init n = 1E+04, A = 0.01, p = 100 The next table presents the results for multi, jagged and linear array. I unrolled the loop 8-times to get higher speedup. Each time represents one computation.
const int n = (int)1E+04;
const int p = 100;
double s = 0;
double[,] multi = new double[n, n];
Stopwatch watch = new Stopwatch();
for (int k = 0; k < n; k++)
for (int h = 0; h < n; h++)
multi[k, h] = 0.01;
watch.Start();
for (int o = 0; o < p; o++)
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
s += multi[i, j];
watch.Stop();
Console.WriteLine("multi sum time " + watch.ElapsedMilliseconds / p + " ms.");
watch.Reset();
multi = null;
double[][] jagged = new double[n][];
for (int k = 0; k < n; k++)
{
jagged[k] = new double[n];
for (int h = 0; h < n; h++)
jagged[k][h] = 0.01;
}
s = 0;
watch.Start();
for (int o = 0; o < p; o++)
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
s += jagged[i][j];
watch.Stop();
Console.WriteLine("jagged sum time " + watch.ElapsedMilliseconds / p + " ms.");
watch.Reset();
jagged = null;
double[] linear = new double[n * n];
for (int k = 0; k < n; k++)
for (int h = 0; h < n; h++)
linear[k * n + h] = 0.01;
s = 0;
watch.Start();
for (int o = 0; o < p; o++)
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
s += linear[i * n + j];
watch.Stop();
Console.WriteLine("linear sum time " + watch.ElapsedMilliseconds / p + " ms.");
watch.Reset();And the code for unrolling the loops. const int n = (int)1E+04;
const int p = 10;
double s = 0;
double[,] multi = new double[n, n];
Stopwatch watch = new Stopwatch();
for (int k = 0; k < n; k++)
for (int h = 0; h < n; h++)
multi[k, h] = 0.01;
watch.Start();
for (int o = 0; o < p; o++)
for (int i = 0; i < n; i+=8)
for (int j = 0; j < n; j++)
{
s += multi[i, j];
s += multi[i+1, j];
s += multi[i+2, j];
s += multi[i+3, j];
s += multi[i+4, j];
s += multi[i+5, j];
s += multi[i+6, j];
s += multi[i+7, j];
}
watch.Stop();
Console.WriteLine("unroll multi sum time " + watch.ElapsedMilliseconds / p + " ms.");
watch.Reset();
multi = null;
double[][] jagged = new double[n][];
for (int k = 0; k < n; k++)
{
jagged[k] = new double[n];
for (int h = 0; h < n; h++)
jagged[k][h] = 0.01;
}
s = 0;
watch.Start();
for (int o = 0; o < p; o++)
for (int i = 0; i < n; i+=8)
for (int j = 0; j < n; j++)
{
s += jagged[i][j];
s += jagged[i+1][j];
s += jagged[i+2][j];
s += jagged[i+3][j];
s += jagged[i+4][j];
s += jagged[i+5][j];
s += jagged[i+6][j];
s += jagged[i+7][j];
}
watch.Stop();
Console.WriteLine("unroll jagged sum time " + watch.ElapsedMilliseconds / p + " ms.");
watch.Reset();
jagged = null;
double[] linear = new double[n * n];
for (int k = 0; k < n; k++)
for (int h = 0; h < n; h++)
linear[k * n + h] = 0.01;
s = 0;
watch.Start();
for (int o = 0; o < p; o++)
for (int i = 0; i < n; i+=8)
for (int j = 0; j < n; j++)
{
s += linear[i * n + j];
s += linear[(i + 1) * n + j];
s += linear[(i + 2) * n + j];
s += linear[(i + 3) * n + j];
s += linear[(i + 4) * n + j];
s += linear[(i + 5) * n + j];
s += linear[(i + 6) * n + j];
s += linear[(i + 7) * n + j];
}
watch.Stop();
Console.WriteLine("unroll linear sum time " + watch.ElapsedMilliseconds / p + " ms.");
watch.Reset();TrackbacksWeblogs that reference this entry
|
|
|