Stopwatch startup issues - c#

I've got a c# program that tests a sort algorithm and it's performance by using a instance of the Stopwatch class.
So far everything is working correctly and I am getting the expected tick results except in the first run.Somehow the Stopwatch class needs about 900 ticks longer for the first calculation.
Do I have to initiate the Stopwatch class somehow different or is there any way to fix this?
static void Main() {
watch = new Stopwatch();
int amount = 10; // Amount of arrays to test
long[, ] stats= new long[3, amount]; // Array that stores ticks for every size (100,1000,10000) 'amount'-times
for (int size = 100, iteration = 0; size <= 10000; size *= 10, iteration++) {
for (int j = 0; j < amount; j++) {
stats[iteration, j] = TestSort(size); // Save ticks for random tested array in stats
}
}
PrintStats(stats);
}
public static long TestSort(int length) {
int[] testArray = GenerateRandomArray(length); // Generate a random array with size of length
watch.Reset();
watch.Start();
sort(testArray);
watch.Stop();
return watch.ElapsedTicks;
}
public static void PrintStats(long[, ] array) {
for (int i = 0; i < array.GetLength(0); i++) {
Console.Write("[");
for (int j = 0; j < array.GetLength(1); j++) {
Console.Write(array[i, j]);
if (j < array.GetLength(1) - 1) {
Console.Write(",");
}
}
Console.Write("]\n");
}
}
// Sample output
// Note that first entry is about 900 ticks longer then the other ones with size 100
[1150,256,268,262,261,262,263,261,263,262]
[19689,20550,20979,22953,19913,20578,19693,19945,19811,19970]
[1880705,1850265,3006533,1869953,1900301,1846915,1840681,1801887,1931206,2206952]

Related

In C# is it faster to create a Hash Set for searching through a list, rather than searching the list itself? [duplicate]

This question already has answers here:
HashSet vs. List performance
(12 answers)
Closed 9 months ago.
I have two lists of strings, and I need to check to see if there are any matches, and I have to do this at a minimum of sixty times a second, but this can scale up to thousands of times a second.
Right now, the lists are both small; one is three, and another might have a few dozen elements at most, but the currently small list is probably gonna grow.
Would it be faster to do this:
for (int i = 0; i < listA.Length; i++)
{
for (int j = 0; j < listB.Length; j++) {
if (listA[i] == listB[j])
{
// do stuff
}
}
}
Or to do this:
var hashSetB = new HashSet<string>(listB.Length);
for (int i = 0; i < listB.Length; i++)
{
hashSetB.Add(listB[i]);
}
for (int i = 0; i < listA.Length; i++)
{
if (hashSetB.Contains(listA[i])) {
// do stuff
}
}
ListA and ListB when they come to me, will always be lists; I have no control over them.
I think the core of my question is that I don't know how long var hashSetB = new HashSet<string>(listB.Length); takes, so I'm not sure the change would be good or bad for smaller lists.
Was curious so here's some code I wrote to test it. From what I got back, HashSet was near instantaneous whereas nested loops were slow. Makes sense as you've essentially taken something where you needed to do lengthA * lengthB operations and simplified it to lengthA + lengthB operation.
const int size = 20000;
var listA = new List<int>();
for (int i = 0; i < size; i++)
{
listA.Add(i);
}
var listB = new List<int>();
for (int i = size - 5; i < 2 * size; i++)
{
listB.Add(i);
}
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < listA.Count; i++)
{
for (int j = 0; j < listB.Count; j++)
{
if (listA[i] == listB[j])
{
Console.WriteLine("Nested loop match");
}
}
}
long timeTaken1 = sw.ElapsedMilliseconds;
sw.Restart();
var hashSetB = new HashSet<int>(listB.Count);
for (int i = 0; i < listB.Count; i++)
{
hashSetB.Add(listB[i]);
}
for (int i = 0; i < listA.Count; i++)
{
if (hashSetB.Contains(listA[i]))
{
Console.WriteLine("HashSet match");
}
}
long timeTaken2 = sw.ElapsedMilliseconds;
Console.WriteLine("Time Taken Nested Loop: " + timeTaken1);
Console.WriteLine("Time Taken HashSet: " + timeTaken2);
Console.ReadLine();

Matrix smallest number

So this code should work, but i cant figure out the problem.
It worked me once before... But now i only get back 0 as a result.
I know it should be obvious but i cant see it.
namespace ConsoleApp5
{
class Program
{
private static void Main(string[] args)
{Console.WriteLine("The SmallestNumber in the given matrix is : {0}", SmallestNumber());
Console.ReadKey();
}
public static int SmallestNumber()
{
int n = 10;
int m = 10;
int[,] TempMatrix = new int[n, m];
Random r = new Random();
int smallest = TempMatrix[0,0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
TempMatrix[i, j] = r.Next(10, 3000);
if (smallest > TempMatrix[i,j])
{
smallest = TempMatrix[i, j];
}
Console.WriteLine(string.Format("{0}\t", TempMatrix[i, j]));
}
}
return smallest;
}
}
}
When you initialize smallest, TempMatrix[0,0] has the value 0. All the random numbers you generate are between 10 and 3000, so all the numbers in the matrix are greater than smallest, since it is 0.
Setting smallest initially to int.MaxValue should solve the problem.

C# Array / List performance difference

Consider the following methods:
static Stopwatch ArrayTest(int size)
{
var arr = new int[size];
Stopwatch stw = new Stopwatch();
stw.Start();
for (int i = 0; i < size; i++)
{
arr[i] = i / div;
}
var rnd = new Random(1);
var sz2 = size / div;
for (int i = 0; i < sz2; i++)
{
var sz = size - i;
var ix = rnd.Next(sz);
Array.Copy(arr, ix + 1, arr, ix, size - ix - 1);
arr[sz - 1] = 0;
}
double sum = 0.0;
for (int i = 0; i < size - sz2; i++)
{
sum += arr[i];
}
stw.Stop();
Console.Write(" Array: {0}", sum);
return stw;
}
static Stopwatch ListTest(int size)
{
var lst = new List<int>();
Stopwatch stw = new Stopwatch();
stw.Start();
for (int i = 0; i < size; i++)
{
lst.Add(i / div);
}
var rnd = new Random(1);
var sz2 = size / div;
for (int i = 0; i < sz2; i++)
{
var ix = rnd.Next(lst.Count);
lst.RemoveAt(ix);
}
double sum = 0.0;
for (int i = 0; i < lst.Count; i++)
{
sum += lst[i];
}
stw.Stop();
Console.Write(" List: {0}", sum);
return stw;
}
div = 2 and size = 200000.
Running this (complied at Release) produces the following:
Array: 5012641699 12.8367529 s
List: 5012641699 6.1027289 s
According to http://referencesource.microsoft.com/#mscorlib List.RemoveAt is implemented like this:
// Removes the element at the given index. The size of the list is
// decreased by one.
//
public void RemoveAt(int index) {
if ((uint)index >= (uint)_size) {
ThrowHelper.ThrowArgumentOutOfRangeException();
}
Contract.EndContractBlock();
_size--;
if (index < _size) {
Array.Copy(_items, index + 1, _items, index, _size - index);
}
_items[_size] = default(T);
_version++;
}
So I wonder why the ArrayTest requires twice the time that ListTest does. It seems to me that they are both doing pretty much the same thing, in fact I'd expect ArrayTest to be faster due to less overhead. Perhaps I have missed something obvious?
Update
Let me explain the example. The idea was to measure the performance under conditions of random deletes (while still retaining indexed access). The first part of each method initializes an array/list where each element in the array is 1/2 the index (integer division). The next part randomly removes 1/2 the elements. The last loop simply sums the values remaining in the array/list which is used as a checksum (to compare results). Profiling the code shows that in ArrayTest the Array.Copy uses the most time and in ListTest the lst.RemoveAt uses the most time.
I will attempt to replicate the behavior in a simpler example and update it here.
The problem seems to be with the line:
Array.Copy(arr, ix + 1, arr, ix, size - ix - 1);
in method ArrayTest. It should read
Array.Copy(arr, ix + 1, arr, ix, sz - ix - 1);
since the variable size is not changed when the array is resized, instead sz, the actual size, is calculated in each iteration.
There is a flaw in your test program. You've made it overly convoluted and thus hard to prove on paper. The only way to figure out what your code is doing is by debugging, hand-calculating everything.
So instead I made a simpler test.
void Main()
{
const int LENGTH = 200000;
Stopwatch sw = Stopwatch.StartNew();
var a = new int[LENGTH];
for (int index = LENGTH-1; index > 0; index--)
Array.Copy(a, 1, a, 0, index);
sw.Stop();
sw.ElapsedMilliseconds.Dump();
var l = new List<int>(a);
sw = Stopwatch.StartNew();
for (int index = LENGTH-1; index > 0; index--)
l.RemoveAt(0);
sw.Stop();
sw.ElapsedMilliseconds.Dump();
}
It simply "removes" the 0th element of an array, and a list. The results on my machine are:
3366
3442
3270
3242
3343
3385
That's 3 runs.

method inline still slower than manually refactor (merge) into same method?

I used to think if a method is inlined, then theoretically it is identical to the merge of the method and the calling method, but the benchmark showed there is slightly difference in performance
e.g. this takes 100ms
public long TestA()
{
long ret = 0;
for (int n = 0; n < testSize; n++)
{
for (int i = 0; i < a; i++)
for (int j = 0; j < b; j++)
{
ret += myArray[i][j];
}
}
return ret;
}
this takes 110ms (if I force MethodImplOptions.NoInlining on GetIt then it will be 400ms, so I assume it is auto inlined)
public long TestB()
{
long ret = 0;
for (int n = 0; n < testSize; n++)
{
for (int i = 0; i < a; i++)
for (int j = 0; j < b; j++)
{
ret += GetIt(i, j);
}
}
return ret;
}
int GetIt(int x, int y)
{
return myArray[x][y];
}
OK, I attach a snippet of benchmark function i used
public static void RunTests(Func<long> myTest)
{
const int numTrials = 100;
Stopwatch sw = new Stopwatch();
double[] sample = new double[numTrials];
Console.WriteLine("Checksum is {0:N0}", myTest());
sw.Start();
myTest();
sw.Stop();
Console.WriteLine("Estimated time per test is {0:N0} ticks\n", sw.ElapsedTicks);
if (sw.ElapsedTicks < 100)
{
Console.WriteLine("Ticks per test is less than 100 ticks. Suggest increase testSize.");
return;
}
if (sw.ElapsedTicks > 10000)
{
Console.WriteLine("Ticks per test is more than 10,000 ticks. Suggest decrease testSize.");
return;
}
for (int i = 0; i < numTrials / 3; i++)
{
myTest();
}
string testName = myTest.Method.Name;
Console.WriteLine("----> Starting benchmark {0}\n", myTest.Method.Name);
for (int i = 0; i < numTrials; i++)
{
GC.Collect();
GC.WaitForPendingFinalizers();
sw.Restart();
myTest();
sw.Stop();
sample[i] = sw.ElapsedTicks;
}
double testResult = DataSetAnalysis.Report(sample);
DataSetAnalysis.ConsistencyAnalyze(sample, 0.1);
Console.WriteLine();
for (int j = 0; j < numTrials; j = j + 5)
Console.WriteLine("{0,8:N0} {1,8:N0} {2,8:N0} {3,8:N0} {4,8:N0}", sample[j], sample[j + 1], sample[j + 2], sample[j + 3], sample[j + 4]);
Console.WriteLine("\n----> End of benchmark");
}
The resulting number of IL instructions differs slightly, the maxstack differs significantly:
TestA:
// Code size 78 (0x4e)
.maxstack 2
TestB:
// Code size 88 (0x58)
.maxstack 4
GetIt:
// Code size 7 (0x7)
.maxstack 1
C# does inline at JIT, so whether inline or not IL doesn't change.
MethodImplOptions.NoInlining is not the same as inline keyword in F#

Make c# matrix code faster

Working on some matrix code, I'm concerned of performance issues.
here's how it works : I've a IMatrix abstract class (with all matrices operations etc), implemented by a ColumnMatrix class.
abstract class IMatrix
{
public int Rows {get;set;}
public int Columns {get;set;}
public abstract float At(int row, int column);
}
class ColumnMatrix : IMatrix
{
private data[];
public override float At(int row, int column)
{
return data[row + columns * this.Rows];
}
}
This class is used a lot across my application, but I'm concerned with performance issues.
Testing only read for a 2000000x15 matrix against a jagged array of the same size, I get 1359ms for array access agains 9234ms for matrix access :
public void TestAccess()
{
int iterations = 10;
int rows = 2000000;
int columns = 15;
ColumnMatrix matrix = new ColumnMatrix(rows, columns);
for (int i = 0; i < rows; i++)
for (int j = 0; j < columns; j++)
matrix[i, j] = i + j;
float[][] equivalentArray = matrix.ToRowsArray();
TimeSpan totalMatrix = new TimeSpan(0);
TimeSpan totalArray = new TimeSpan(0);
float total = 0f;
for (int iteration = 0; iteration < iterations; iteration++)
{
total = 0f;
DateTime start = DateTime.Now;
for (int i = 0; i < rows; i++)
for (int j = 0; j < columns; j++)
total = matrix.At(i, j);
totalMatrix += (DateTime.Now - start);
total += 1f; //Ensure total is read at least once.
total = total > 0 ? 0f : 0f;
start = DateTime.Now;
for (int i = 0; i < rows; i++)
for (int j = 0; j < columns; j++)
total = equivalentArray[i][j];
totalArray += (DateTime.Now - start);
}
if (total < 0f)
logger.Info("Nothing here, just make sure we read total at least once.");
logger.InfoFormat("Average time for a {0}x{1} access, matrix : {2}ms", rows, columns, totalMatrix.TotalMilliseconds);
logger.InfoFormat("Average time for a {0}x{1} access, array : {2}ms", rows, columns, totalArray.TotalMilliseconds);
Assert.IsTrue(true);
}
So my question : how can I make this thing faster ? Is there any way I can make my ColumnMatrix.At faster ?
Cheers !
Remove abstract class IMatrix. This is wrong because it's not interface and calling overridden methods is slower than calling final (aka non-modifier methods).
You could use unsafe code (pointers) to get elements of the array without array-bounds-checks (faster, but more work and unsafe)
The array code you've written can be optimized easily enough as it's clear that you're accessing memory sequentially. This means the JIT compiler will probably do a better job at converting it to native code and that will result in better performance.Another thing you're not considering is that inlining is still hit and miss so if your At method (why not using an indexer property, by the way?) is not inlined you'll suffer a huge performance hit due to the use of call and stack manipulation. Finally you should consider sealing the ColumnMatrix class because that will make the optimization much easier for the JIT compiler (call is definitely better than callvirt).
If a two-dimensional array performs so much better, which don't you use a two-dimensional array for your class's internal storage, rather than the one-dimensional one with the overhead of calculating the index?
As you are using DateTime.Now to measure the performance, the result is quite random. The resolution of the clock is something like 1/20 second, so instead of measuring the actual time, you are measuring where in the code the clock happens to tick.
You should use the Stopwatch class instead, which has much higher resolution.
For every access of an element you do a multiplication: row + columns * this.Rows.
You might see if internally you could also use a 2 dimensional array
You also gain extra overhead that the thing is abstracted away in a class. You are doing an extra method call everytime you access an element in the matrix
Change to this:
interface IMatrix
{
int Rows {get;set;}
int Columns {get;set;}
float At(int row, int column);
}
class ColumnMatrix : IMatrix
{
private data[,];
public int Rows {get;set;}
public int Columns {get;set;}
public float At(int row, int column)
{
return data[row,column];
}
}
You're better off with the interface than the abstract class - if you need common functions of it add extension methods for the interface.
Also a 2D matrix is quicker than either the jagged one or your flattened one.
You can use Parallel programming for speed up your algorithm.
You can compile this code, and compare the performance for normal matrix equations (MultiplyMatricesSequential function) and parallel matrix equations (MultiplyMatricesParallel function). You have implemented compare functions of performance of this methods (in Main function).
You can compile this code under Visual Studio 2010 (.NET 4.0)
namespace MultiplyMatrices
{
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
class Program
{
#region Sequential_Loop
static void MultiplyMatricesSequential(double[,] matA, double[,] matB,
double[,] result)
{
int matACols = matA.GetLength(1);
int matBCols = matB.GetLength(1);
int matARows = matA.GetLength(0);
for (int i = 0; i < matARows; i++)
{
for (int j = 0; j < matBCols; j++)
{
for (int k = 0; k < matACols; k++)
{
result[i, j] += matA[i, k] * matB[k, j];
}
}
}
}
#endregion
#region Parallel_Loop
static void MultiplyMatricesParallel(double[,] matA, double[,] matB, double[,] result)
{
int matACols = matA.GetLength(1);
int matBCols = matB.GetLength(1);
int matARows = matA.GetLength(0);
// A basic matrix multiplication.
// Parallelize the outer loop to partition the source array by rows.
Parallel.For(0, matARows, i =>
{
for (int j = 0; j < matBCols; j++)
{
// Use a temporary to improve parallel performance.
double temp = 0;
for (int k = 0; k < matACols; k++)
{
temp += matA[i, k] * matB[k, j];
}
result[i, j] = temp;
}
}); // Parallel.For
}
#endregion
#region Main
static void Main(string[] args)
{
// Set up matrices. Use small values to better view
// result matrix. Increase the counts to see greater
// speedup in the parallel loop vs. the sequential loop.
int colCount = 180;
int rowCount = 2000;
int colCount2 = 270;
double[,] m1 = InitializeMatrix(rowCount, colCount);
double[,] m2 = InitializeMatrix(colCount, colCount2);
double[,] result = new double[rowCount, colCount2];
// First do the sequential version.
Console.WriteLine("Executing sequential loop...");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
MultiplyMatricesSequential(m1, m2, result);
stopwatch.Stop();
Console.WriteLine("Sequential loop time in milliseconds: {0}", stopwatch.ElapsedMilliseconds);
// For the skeptics.
OfferToPrint(rowCount, colCount2, result);
// Reset timer and results matrix.
stopwatch.Reset();
result = new double[rowCount, colCount2];
// Do the parallel loop.
Console.WriteLine("Executing parallel loop...");
stopwatch.Start();
MultiplyMatricesParallel(m1, m2, result);
stopwatch.Stop();
Console.WriteLine("Parallel loop time in milliseconds: {0}", stopwatch.ElapsedMilliseconds);
OfferToPrint(rowCount, colCount2, result);
// Keep the console window open in debug mode.
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
}
#endregion
#region Helper_Methods
static double[,] InitializeMatrix(int rows, int cols)
{
double[,] matrix = new double[rows, cols];
Random r = new Random();
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
matrix[i, j] = r.Next(100);
}
}
return matrix;
}
private static void OfferToPrint(int rowCount, int colCount, double[,] matrix)
{
Console.WriteLine("Computation complete. Print results? y/n");
char c = Console.ReadKey().KeyChar;
if (c == 'y' || c == 'Y')
{
Console.WindowWidth = 180;
Console.WriteLine();
for (int x = 0; x < rowCount; x++)
{
Console.WriteLine("ROW {0}: ", x);
for (int y = 0; y < colCount; y++)
{
Console.Write("{0:#.##} ", matrix[x, y]);
}
Console.WriteLine();
}
}
}
#endregion
}
}

Categories

Resources