How to calculate the average of multiple Stopwatch times? - c#

So basically what i'm trying to do is calculate the average of all the Stop Watch times that my for loop produces and out put it to the Console. i know how to take an average but i dont know how to apply it to Stopwatch times. Please help?
for (int index = 0; index < iterations; index++)
{
// loop to generate an array of random numbers
for (int count = 0; count < arrayOfInts.Length; count++)
{
arrayOfInts[count] = r.Next(numitems);
}
// a random array has been created start the clock and sort it
Stopwatch elpased = new Stopwatch();
elpased.Start();
selectionSort(arrayOfInts);
elpased.Stop();
if (iterations == iterations)
{
var average = elpased.Elapsed;
Console.WriteLine ("Time for ___ sort to complete: " + elpased.Elapsed.ToString ());
}
}
Console.ReadLine();
}
This is what i have so far.

I'd suggest to use ElapsedTicks instead. And you need to store the ticks for each iteration and calculate the average afterwards:
List<long> ticks = new List<long>();
for (int index = 0; index < iterations; index++)
{
// loop to generate an array of random numbers
for (int count = 0; count < arrayOfInts.Length; count++)
{
arrayOfInts[count] = r.Next(numitems);
}
// a random array has been created start the clock and sort it
Stopwatch elapsed = new Stopwatch();
elapsed.Start();
selectionSort(arrayOfInts);
elpased.Stop();
ticks.Add(elapsed.Elapsed.Ticks);
}
double avg = ticks.Average(); // create average of ticks
TimeSpan averageTimeSpan = new TimeSpan((long)avg); // cast needed from double to long
There is a little more elegant way to produce your random number array:
arrayOfInts = Enumerable.Range(0, count).Select(i => r.Next(numitems)).ToArray();
And because LINQ uses deferred execution you could even pre-declare this "query" and call ToArray() in the iteration:
List<long> ticks = new List<long>();
IEnumerable<int> randomQuery = Enumerable.Range(0, count).Select(i => r.Next(numitems));
for (int index = 0; index < iterations; index++)
{
//creates NEW random numbers each time, because of deferred execution
arrayOfInts = randomQuery.ToArray();
...
Another suggestion is to let the Stopwatch measure the whole time and divide the result by iterations. Stopwatches can be resumed:
IEnumerable<int> randomQuery = Enumerable.Range(0, count).Select(i => r.Next(numitems));
Stopwatch elapsed = new Stopwatch(); // only ONE instance needed
for (int index = 0; index < iterations; index++)
{
arrayOfInts = randomQuery.ToArray();
elapsed.Start(); // resumes without a reset
selectionSort(arrayOfInts);
elpased.Stop();
}
TimeSpan averageTimeSpan = new TimeSpan(elapsed.ElapsedTicks/iterations);

Related

fill an array with random numbers using threads in c#

so as said in the tile I'm trying to fill up an array of bytes with random numbers using 16 (in my case) threads, now it takes about six and a half seconds filling up an array with 500000000 bytes using one thread so the logic says that using 16 threads will be at least 10 times faster but then I tried to do this, it took 15 seconds to fill it up, what I did is I gave each thread one segment to fill in the same array
here is the code:
static byte[] nums2 = new byte[500000000];
static Random rnd = new Random(123);
static void fill()
{
for (int i = 0; i < nums.Length; i++)
nums[i] = (byte)rnd.Next(10);
}
static void fillPart(object ID)
{
var part = nums2.Length / Environment.ProcessorCount;
int baseN = (int)ID * part;
for (int i = baseN; i < baseN + part; i++)
nums2[i] = (byte)rnd.Next(10);
Console.WriteLine("Done! " + ID);
}
static void Main(string[] args)
{
Stopwatch watch = new Stopwatch();
watch.Start();
fill();
watch.Stop();
Console.WriteLine("it took " + watch.Elapsed);
Console.WriteLine();
watch.Reset();
watch.Start();
Thread[] threads = new Thread[Environment.ProcessorCount];
for (int i = 0; i < Environment.ProcessorCount; i++)
{
threads[i] = new Thread(fillPart);
threads[i].Start(i);
}
for(int i = 0; i < Environment.ProcessorCount; i++)
threads[i].Join();
watch.Stop();
Console.WriteLine("it took " + watch.Elapsed);
}
}```
would like to understand why is it took 15 seconds or maybe what I did wrong
If it were me, I'd just:
byte[] nums = new byte[500000000];
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
rng.GetBytes(nums);
and be done with it.
If you really want threads:
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
var dop = 8;
var batchSize = 500000000 / dop;
var bigBytes = Enumerable.Range(0, dop).AsParallel().SelectMany(t => {
var bytes = new byte[batchSize];
rng.GetBytes(bytes); //This *IS* thread-safe
return bytes;
}).ToArray();
but I suspect the time spent collating into a new array by SelectMany followed by ToArray might make this more expensive that the single-thread approach.
The problem is you declare the static Random rnd = new Random(int.MaxValue);
If you create the Random instance in fillPart method then the program will finish in one second so the problem in not Thread is rnd.Next(10)
static void fillPart(object ID)
{
Random rnd = new Random(123);
var part = nums2.Length / Environment.ProcessorCount;
int baseN = (int)ID * part;
int co = 0;
for (int i = baseN; i < baseN + part; i++)
{
nums2[i] = (byte)rnd.Next(10);
}
//Console.WriteLine("Done! " + ID + co);
}

C# is there a faster way to get max diff between a date set than for loop

I have a list of dates in descending order e.g.
var dates = {date1, date2, date3};
Task is to find the maximum number of days between the dates.
What I have done so far is:
var maxDays = 0;
var previousDate = dates.First();
foreach (var thisDate in dates.Skip(0))
{
maxDays = Max(thisDate - previousDate, maxDays);
previousDate = thisDate;
}
This works fine until I get around 1000+ dates in a list.
Can you recommend any other ways?
Thanks
I would suggest a slightly different approach:
HashSet<TimeSpan> counts = new HashSet<TimeSpan>();
var previousDate = dates.First();
foreach (var thisDate in dates.Skip(1))
{
counts.Add(previousDate - thisDate);
previousDate = thisDate;
}
var max = counts.Max();
The idea is to not calculate the max for each iteration but rather collect the differences and then let the Max be a set operation.
Using a HashSet also reduces the number of [unique] differences that you will be checking.
I tested this with 200,000 dates and it took less than 300 milliseconds.
Assuming dates is a List<DateTime>, you can just run a loop that starts with the first element and goes until the second-to-last element. Then inside the loop, you compare the current element with the next one, and if the difference is greater than your current max, reset it:
double maxDays = 0;
for (int i = 0; i < dates.Count - 1; i++)
{
var diff = (dates[i + 1] - dates[i]).TotalDays;
if (diff > maxDays ) maxDays = diff;
}
Here's a benchmark test that shows it takes about 10 milliseconds to process 1 million items:
private static void Main()
{
var numDates = 1000000;
var dates = new List<DateTime>();
// initialize list with random dates
var rnd = new Random();
for (int i = 0; i < numDates; i++)
{
var day = rnd.Next(1, 29);
var month = rnd.Next(1, 13);
var year = rnd.Next(DateTime.MinValue.Year, DateTime.MaxValue.Year + 1);
dates.Add(new DateTime(year, month, day));
}
// Sort the list descending
dates = dates.OrderByDescending(d => d).ToList();
// find the two neighbors with the greatest distance
double maxDays = 0;
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < dates.Count - 1; i++)
{
var diff = (dates[i] - dates[i + 1]).TotalDays;
if (diff > maxDays) maxDays = diff;
}
sw.Stop();
// Display results
Console.WriteLine($"The greatest difference was {maxDays} days.");
Console.WriteLine($"The comparison of {dates.Count} items took {sw.ElapsedMilliseconds} milliseconds");
Console.WriteLine("\nDone!\nPress any key to exit...");
Console.ReadKey();
}
Output

How to create a loop that ask the user for two numbers, one will be for the length of the array, and the other for how many times the loop iterates

public static void sortInterations()
{
Random r = new Random ();
Console.WriteLine ("Please enter the number of items in the array that will be sorted:");
int numitems = Convert.ToInt32(Console.ReadLine());
int[] arrayOfInts = new int[numitems];
Console.WriteLine ("Please enter a number for iterations:");
int iterations = Convert.ToInt32 (Console.ReadLine ());
TimeSpan runningTime;
for (int index = 0; index < iterations; index++)
{
for (int count = 0; count < arrayOfInts.Length; count++)
{
arrayOfInts [count] = r.Next (numitems);
}
}
DateTime startTime = DateTime.Now;
selectionSort (arrayOfInts);
runningTime = DateTime.Now.Subtract(startTime);
Console.WriteLine ("Time for ___ sort to complete: " + runningTime.ToString(#"mm\:ss\.ffffff"));
sortInterations ();
}
This is what i have so far! Basically i want to fill the array with random numbers and then sort it using bubble sort the number of times that the user entered in for the variable iterations and then prints out how long it took.
Hope this helps. You may want to get a new seed on each iteration of creating a new array of random ints to avoid getting the same or close to the same numbers.
public static void sortInterations()
{
Random r = new Random();
Console.WriteLine("Please enter the number of items in the array that will be sorted:");
// no checking for invalid input i.e. "aA" will crash here when you try to convert
int numitems = Convert.ToInt32(Console.ReadLine());
int[] arrayOfInts = new int[numitems];
Console.WriteLine("Please enter a number for iterations:");
// no checking for invalid input i.e. "aA" will crash here when you try to convert
int iterations = Convert.ToInt32(Console.ReadLine());
// loop for each random array
for (int index = 0; index < iterations; index++)
{
// loop to generate an array of random numbers
for (int count = 0; count < arrayOfInts.Length; count++)
{
arrayOfInts[count] = r.Next(numitems);
}
// a random array has been created start the clock and sort it
Stopwatch elpased = new Stopwatch();
elpased.Start();
selectionSort(arrayOfInts);
elpased.Stop();
Console.WriteLine("Sort array Number: " + index + " Time for sort to complete in milliseconds: " + elpased.ElapsedMilliseconds.ToString());
}
Console.ReadLine();
}

Logging the time it takes to fill a LinkedList and Array

This Console-application is a bit strange but kinda funny, if it works. First, I'm clocking the time it takes to fill a LinkedList with 4.000.000 elements, with random numbers. Then I'm searching for 100 random elements in that LinkedList. And between this I'm writing out the time it took to fill and find the elements.
After that I'm trying to do the same thing again, but with an Array. First filling it, then looking for 100 random elements. And then I'm sorting the array, to see the difference between looking for 100 random elements in a unsorted vs sorted array. And then typing the time again.
The problem is, after I've filled the LinkedList, and found the elements in the LinkedList, I'm starting to fill the Array with a loop. And I get a infinite loop. I really don't know what's wrong ATM.
I suggest, if you want to help, that you copy the code I'm pasting into this question, so you understand how it should look for all the parts of the program.
Code:
public static bool sokning(int[] a, int b)
{
bool sant = false;
Random rand = new Random();
Stopwatch watchFindArray = new Stopwatch();
Console.Write("Letar efter tal: ");
watchFindArray.Start();
int myint = 0;
for (int iii = 0; iii < a.Length; iii++)
{
b = rand.Next();
Console.Write("#");
myint = Array.BinarySearch(a, b);
if (myint < 0)
{
sant = false;
}
else
{
sant = true;
}
}
watchFindArray.Stop();
if (sant == true)
{
Console.WriteLine("\nFann alla element efter " + watchFindArray.Elapsed.TotalSeconds + " sekunder.");
return true;
}
else
{
return false;
}
}
public static void körMetod()
{
const int MAX = 40000000;
int[] array = new int[MAX];
int hittamig2 = 0;
Random rand2 = new Random();
Stopwatch watchArray = new Stopwatch();
Console.WriteLine("\nStartar Array...");
watchArray.Start();
Console.Write("Position: ");
for (int ii = 0; ii < MAX; ii++)
{
array[ii] = rand2.Next();
if (array.Length % 1000000 == 0)
{
Console.Write("#");
}
}
watchArray.Stop();
Console.WriteLine("\nTid: " + watchArray.Elapsed.TotalSeconds + " sekunder att fylla en array.");
Console.WriteLine("Letar efter tal: ");
bool sant = sokning(array, hittamig2);
Console.WriteLine("Sorterar arrayen.");
Array.Sort(array);
sant = sokning(array, hittamig2);
if (sant == false)
{
Console.WriteLine("\nHittade inte alla element i arrayen.");
Console.ReadLine();
}
else
{
Console.WriteLine("Klar!");
Console.ReadLine();
}
}
static void Main(string[] args)
{
Random rnd = new Random();
const int MAX = 40000000;
LinkedList<int> lankadLista = new LinkedList<int>();
Stopwatch watchLinkedList = new Stopwatch();
Console.WriteLine("Startar LinkedList...");
watchLinkedList.Start();
Console.Write("Position: ");
for (int i = 0; i < MAX; i++)
{
lankadLista.AddLast(rnd.Next());
if (lankadLista.Count() % 1000000 == 0)
{
Console.Write("#");
}
}
watchLinkedList.Stop();
Console.WriteLine("\nTid: " + watchLinkedList.Elapsed.TotalSeconds + " sekunder att fylla en LinkedList.");
Stopwatch watchFindLinkedList = new Stopwatch();
int hittaMig;
Console.Write("Letar efter tal: ");
watchFindLinkedList.Start();
for (int j = 0; j < 100; j++)
{
hittaMig = rnd.Next();
Console.Write("#");
lankadLista.Find(hittaMig);
}
watchFindLinkedList.Stop();
Console.WriteLine("\nFann alla element efter " +
watchFindLinkedList.Elapsed.TotalSeconds + " sekunder.");
Console.ReadLine();
körMetod();
}
Best Regards.
You are not in an infinite loop, the problem is that it the following code:
for (int ii = 0; ii < MAX; ii++)
{
array[ii] = rand2.Next();
if (array.Length % 1000000 == 0)
{
Console.Write("#");
}
}
The inner condition is array.Length % 1000000 == 0 which is always true because the size of array is always 40000000 as you initialized it:
const int MAX = 40000000;
int[] array = new int[MAX];
When you are doing array[ii] = rand2.Next(); you are not changing the length of the array you are just setting one of its cells with a value equals to rand2.Next();.
This causes the Console.Write("#"); to work in every iteration and also slowing your loop dramatically.
To fix this, just change:
if (array.Length % 1000000 == 0)
to:
if (ii % 1000000 == 0)
You don't want to add new item at the end of the array every time because, resizing the array reallocates the array every time which is super slow but you can do it using the Array.Resize method (no reason for you to do it)
I think you have a big problem in the routine that searches the Array. (sokning)
Where is the code that searches for only 100 elements?
It seems that your are searching a random generated number for 40 millions times. Just fixing the Console.Write("#") to write correctly at every million point is not enough. I think that the big delay that let you think to have an infinite loop is in your code that search 40 millions of random generated numbers in an array of 40 millions of numbers
Of course this is not very "responsive" (considering also that you call this method two times)
public static bool sokning(int[] a, int b)
{
bool sant = false;
Random rand = new Random();
Stopwatch watchFindArray = new Stopwatch();
Console.Write("Letar efter tal: ");
watchFindArray.Start();
int myint = 0;
// Search only 100 numbers like you do in the linked list
for (int iii = 0; iii < 100; iii++)
{
b = rand.Next();
Console.Write("#");
myint = Array.BinarySearch(a, b);
if (myint < 0)
{
sant = false;
}
else
{
sant = true;
}
}
watchFindArray.Stop();
if (sant == true)
{
Console.WriteLine("\nFann alla element efter " + watchFindArray.Elapsed.TotalSeconds + " sekunder.");
return true;
}
else
{
return false;
}
}
There are also two minor problems.
Why passing the variable b inside the sokning method? The original value is never used and when you start the loop to search a random generated number the b variable os overwritten. So I think you could remove it
The second problem is the result of this sokning method. You set the sant variable to true or false at every loop. So the latest loop wins. In other words, if the latest loop finds a match you return true or false if not. If some previous loop has a different result, it is totally lost for the callers of sokning.

Find intersection group of sorted integer arrays

Let's we have some integer short sorted arrays and we need to find intersection equal or more then predefined constant.
Here is code and it demonstrates what i want to do better then i can explain it in words.
The problem is SPEED. My code is working very slow. It takes about 15 sec on 2000 elements array(on my slow machine). Ofcourse i can implement my own intersection method and parallize code but it give a very limited improvement. Execution time growing as N^2 or something and already for 500k arrays it takes a very very long time. So how can i rewrite algorithm for better perfomance? I am not limited c# language maybe CPU or GPU has good special instructions for such job.
Example:
Input:
1,3,7,8
2,3,8,10
3,10,11,12,13,14
minSupport = 1
Output:
1 and 2: 2, 8
1 and 3: 3
2 and 3: 3, 10
var minSupport = 2;
var random = new Random(DateTime.Now.Millisecond);
// Numbers is each array are unique
var sortedArrays = Enumerable.Range(0,2000)
.Select(x => Enumerable.Range(0,30).Select(t => random.Next(1000)).Distinct()
.ToList()).ToList();
var result = new List<int[]>();
var resultIntersection = new List<List<int>>();
foreach (var array in sortedArrays)
{
array.Sort();
}
var sw = Stopwatch.StartNew();
//****MAIN PART*****//
for (int i = 0; i < sortedArrays.Count-1; i++)
{
for (int j = i+1; j < sortedArrays.Count; j++)
{
var intersect = sortedArrays[i].Intersect(sortedArrays[j]).ToList();
if(intersect.Count()>=minSupport)
{
result.Add( new []{i,j});
resultIntersection.Add(intersect);
}
}
}
//*****************//
sw.Stop();
Console.WriteLine(sw.Elapsed);
EDIT:
Now it takes about 9 sec vs 15 sec with old algorithm on 2000 elements. Well...ofcourse it is not fast enough.
//****MAIN PART*****//
// This number(max value which array can contains) is known
var maxValue = 1000;
var reverseIndexDict = new Dictionary<int,List<int>>();
for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}
for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}
var tempArr = new List<int>();
for (int i = 0; i < sortedArrays.Count; i++)
{
tempArr.Clear();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
tempArr.AddRange(reverseIndexDict[j]);
}
result.AddRange(tempArr.GroupBy(x => x).Where(x => x.Count()>=minSupport).Select(x => new[]{i,x.Key}).ToList());
}
result = result.Where(x => x[0]!=x[1]).ToList();
for (int i = 0; i < result.Count; i++)
{
resultIntersection.Add(sortedArrays[result[i][0]].Intersect(sortedArrays[result[i][1]]).ToList());
}
//*****************//
EDIT:
Some improvent.
//****MAIN PART*****//
// This number(max value which array can contains) is known
var maxValue = 1000;
var reverseIndexDict = new List<int>[maxValue];
for (int i = 0; i < maxValue; i++)
{
reverseIndexDict[i] = new List<int>();
}
for (int i = 0; i < sortedArrays.Count; i++)
{
for (int j = 0; j < sortedArrays[i].Count; j++)
{
reverseIndexDict[sortedArrays[i][j]].Add(i);
}
}
for (int i = 0; i < sortedArrays.Count; i++)
{
var tempArr = new Dictionary<int, List<int>>();
for (int j = 0; j < sortedArrays[i].Count; j++)
{
var sortedArraysij = sortedArrays[i][j];
for (int k = 0; k < reverseIndexDict[sortedArraysij].Count; k++)
{
if(!tempArr.ContainsKey(reverseIndexDict[sortedArraysij][k]))
{
tempArr[reverseIndexDict[sortedArraysij][k]] = new[]{sortedArraysij}.ToList();
}
else
{
tempArr[reverseIndexDict[sortedArraysij][k]].Add(sortedArrays[i][j]);
}
}
}
for (int j = 0; j < reverseIndexDict.Length; j++)
{
if(reverseIndexDict[j].Count>=minSupport)
{
result.Add(new[]{i,j});
resultIntersection.Add(reverseIndexDict[j]);
}
}
}
// and here we are filtering collections
//*****************//
There are two solutions:
Let us suppose you have 3 sorted arrays and you have to find the intersection between them. Traverse the first array and run a binary search on the rest of the two arrays for the element in first array. If the respective binary search on two list gave positive, then increment the counter of intersection.
result = List
for element in Array1:
status1 = binarySearch(element, Array2)
status2 = binarySearch(element, Array2)
status = status & status
if status == True:
count++
if count == MAX_INTERSECTION:
result.append(element)
break
Time Complexity : N * M * Log(N),
where,
N = Number of element in the array
M = Number of arrays
This solution works only if the number in the arrays are positive integers. Calculate the maximum and the minimum number out of the total elements in all the sorted arrays. As it is sorted, we can determine it by surveying the start and end element of the sorted arrays given. Let the greatest number be max and the lowest number be min. Create an array of size max - min and fill it with zero. Let us suppose you have 3 Arrays, now start traversing the first array and and go to the respective index and increment the value in the previously created array. As mentioned below:
element is 5 in Array 1, the New_array[5]+=1
Traverse all the three sorted list and perform the operation mentioned above. At the end traverse the new_array and look for value equal to 3, these indexes are the intersection result.
Time Complexity : O(N) + O(N) + .. = O(N)
Space Complexity : O(maximum_element - minimum_element)
where,
N = number of elements in the array.

Categories