reimplement a loop using Parallel.For - c#

how to re implement the loop below using Parallel.For?
for (int i = 0; i < data.Length; ++i)
{
int cluster = clustering[i];
for (int j = 0; j < data[i].Length; ++j)
means[cluster][j] += data[i][j]; // accumulate sum
}
getting better performance and speed up is the goal.

You can mostly just replace the outer loop. However, you need to take care with the setting, as you're setting values from multiple threads:
Parallel.For(0, data.Length, i =>
{
int cluster = clustering[i];
for (int j = 0; j < data[i].Length; ++j)
Interlocked.Add(ref means[cluster][j], data[i][j]);
});
However, this may not run any faster, and may actually run significantly slower, as you could easily introduce false sharing since everything is reading from and writing to the same arrays.

Related

Parallel array processing in C#

I have an array of 921600 numbers between 0 and 255.
I need to check each number whether it's above a threshold or not.
Is it possible to check the first- and second half of the array at the same time, to cut down on run time?
What I mean is, is it possible to run the following two for loops in parallel?
for(int i = 0; i < 921600 / 2; i++)
{
if(arr[i] > 240) counter++;
}
for(int j = 921600 / 2; j < 921600; j++)
{
if(arr[j] > 240) counter++;
}
Thank you in advance!
I suggest using Parallel Linq (PLinq) for this
int[] source = ...
int count = source
.AsParallel() // comment this out if you want sequential version
.Count(item => item > 240);
What you are asking is strictly possible as per below.
int counter = 0;
var tasks = new List<Task>();
var arr = Enumerable.Range(0, 921600).ToArray();
tasks.Add(Task.Factory.StartNew(() =>
{
for (int i = 0; i < 921600 / 2; i++)
{
if (arr[i] > 240) counter++;
}
}));
tasks.Add(Task.Factory.StartNew(() =>
{
for (int j = 921600 / 2; j < 921600; j++)
{
if (arr[j] > 240) counter++;
}
}));
Task.WaitAll(tasks.ToArray());
Do not use this code! You will encounter a race condition with incrementing the integer where one thread's increment is lost due to a Read, Read, Write, Write situation. Running this in LinqPad, I ended up with counter being anything between 600000 and 800000. Obviously that range is nowhere near the actual value.
The solution to this race condition is to introduce a lock that means that only one thread can touch the variable at any one time. This negates the ability for the assignment to be multithreaded but allows us to get the correct answer. (This takes 0.042s on my machine for reference)
int counter = 0;
var tasks = new List<Task>();
var arr = Enumerable.Range(0, 921600).ToArray();
var locker = new Object();
tasks.Add(Task.Factory.StartNew(() =>
{
for (int i = 0; i < 921600 / 2; i++)
{
if (arr[i] > 240)
lock (locker)
counter++;
}
}));
tasks.Add(Task.Factory.StartNew(() =>
{
for (int j = 921600 / 2; j < 921600; j++)
{
if (arr[j] > 240)
lock (locker)
counter++;
}
}));
Task.WaitAll(tasks.ToArray());
The solution is indeed to use Parallel Linq as Dmitry has suggested:
Enumerable.Range(0, 921600).AsParallel().Count(x=>x>240);
This takes 0.031s which is quicker than our locking code and still returns the correct answer but removing the AsParallel call makes it run in 0.024s. Running a piece of code in parallel introduces a overhead to manage the threads. Sometimes the performance improvement outweighs this but a surprisingly large amount of the time it doesn't.
The moral of the story is to always run some metrics/timings of your expected data against your implementation of any code to check whether there is actually a performance benefit.
while googling for parallel concepts, came across your query. Might be the below little trick might help you
int n=921600/2;
for(int i=0; i<n; i++)
{
if(arr[i]>240) counter ++;
if(arr[n + i] > 240) counter ++;
}

Jagged array of tasks - Concurrency Issues

I am defining a jagged array of threads (such that each thread can operate on the directory tree of its own) in this manner
Task[][] threads = new Task[InstancesDir.Length][];
for (int i = 0; i < InstancesDir.Length; i++)
{
threads[i] = new Task[InstancesDir[i].Length];
}
for (int i = 0; i < FilesDir.Length; i++)
{
for (int j = 0; j < FilesDir[i].Length; j++)
{
threads[i][j] = Task.Run(() =>
{
Calculate(i, j, InstancesDir, FilesDir, PointSum);
});
}
Task.WaitAll(threads[i]);
}
But in calculate i always get value of j >= FilesDir[i].Length . I have also checked that objects are passed by value except arrays. What could be a workaround for this and what could be the reason for this behavior?
PS. Introducing a shared lock might help in mitigation the concurrency issue but i want to know about the reason for such behavior.
But in calculate i always get value of j >= FilesDir[i].Length
This isn't a concurrency issue, as your for loop is executing on a single thread. This happens because the lambda expression is closing over your i and j variables. This effect is called Closure.
In order to avoid it, create a temp copy before passing both variables to Task.Run:
var tempJ = j;
var tempI = i;
threads[tempI][tempJ] = Task.Run(() =>
{
Calculate(tempI, tempJ, InstancesDir, FilesDir, PointSum);
});

Unreachable Code Detected C#

Im trying to Post an unlimited number of likes but looping the cookies and proxies based on the how many cookies are stored in the array. Apparently i++ is unreachable code. What is the reason for that?
public void PostLikes()
{
PostLike postLike = new PostLike();
for (int i =0;i<this.cookies.ToArray().Length;i++)
{
for (int j = 0; ; j++)
{
postLike.PostLike(this.cookies[i], this.importedProxies[i], this.proxyUsernameTextbox, this.proxyPasswordTextbox, this.postsIds[j]);
}
}
}
The real problem is that:
for (int j = 0; ; j++)
Produces an infinite loop, assuming you don't have any other control statements inside (e.g. break, return, goto, throw)
You probably meant to do something like this:
for (int j = 0; j < this.postsIds.Length; j++)
{
...
}
And don't do this
for (int i =0;i<this.cookies.ToArray().Length;i++)
because
this.cookies.toArray().Length
its evaluating in every iteration of the for loop, you are making 'this.cookies' to array every time so just you get its length? :) You are increasing the complexity of the method
for (int j = 0; ; j++)
This is a dead loop, so i++ won't be reached

Using parallel in C#

I'm new to threading and parallelism. I have this method for a game in C# and need to use parallel iteration. How could I use this on the for loops in the below method?
public int[,] GetLegalMoves()
{
int[,] legalMoves = new int[8, 8];
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
if (IsMoveLegal(i, j)) legalMoves[i, j] = 1;
else legalMoves[i, j] = 0;
return legalMoves;
}
This could be parallelized by parallelizing your outer loop:
public int[,] GetLegalMoves()
{
int[,] legalMoves = new int[8, 8];
Parallel.For(0, 8, i =>
{
for (int j = 0; j < 8; j++)
if (IsMoveLegal(i, j)) legalMoves[i, j] = 1;
else legalMoves[i, j] = 0;
});
return legalMoves;
}
That being said, this will likely cause this to run slower, as an 8x8 matrix is such a small value that the overhead of scheduling the parallel work is likely higher than the gains made, unless IsMoveLegal is a fairly expensive operation.
This will also require that IsMoveLegal be safe to use from multiple threads.

What's better in regards to performance? type[,] or type[][]?

Is it more performant to have a bidimensional array (type[,]) or an array of arrays (type[][]) in C#?
Particularly for initial allocation and item access
Of course, if all else fails... test it! Following gives (in "Release", at the console):
Size 1000, Repeat 1000
int[,] set: 3460
int[,] get: 4036 (chk=1304808064)
int[][] set: 2441
int[][] get: 1283 (chk=1304808064)
So a jagged array is quicker, at least in this test. Interesting! However, it is a relatively small factor, so I would still stick with whichever describes my requirement better. Except for some specific (high CPU/processing) scenarios, readability / maintainability should trump a small performance gain. Up to you, though.
Note that this test assumes you access the array much more often than you create it, so I have not included timings for creation, where I would expect rectangular to be slightly quicker unless memory is highly fragmented.
using System;
using System.Diagnostics;
static class Program
{
static void Main()
{
Console.WriteLine("First is just for JIT...");
Test(10,10);
Console.WriteLine("Real numbers...");
Test(1000,1000);
Console.ReadLine();
}
static void Test(int size, int repeat)
{
Console.WriteLine("Size {0}, Repeat {1}", size, repeat);
int[,] rect = new int[size, size];
int[][] jagged = new int[size][];
for (int i = 0; i < size; i++)
{ // don't count this in the metrics...
jagged[i] = new int[size];
}
Stopwatch watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
rect[i, j] = i * j;
}
}
}
watch.Stop();
Console.WriteLine("\tint[,] set: " + watch.ElapsedMilliseconds);
int sum = 0;
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
sum += rect[i, j];
}
}
}
watch.Stop();
Console.WriteLine("\tint[,] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum);
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
jagged[i][j] = i * j;
}
}
}
watch.Stop();
Console.WriteLine("\tint[][] set: " + watch.ElapsedMilliseconds);
sum = 0;
watch = Stopwatch.StartNew();
for (int cycle = 0; cycle < repeat; cycle++)
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
sum += jagged[i][j];
}
}
}
watch.Stop();
Console.WriteLine("\tint[][] get: {0} (chk={1})", watch.ElapsedMilliseconds, sum);
}
}
I believe that [,] can allocate one contiguous chunk of memory, while [][] is N+1 chunk allocations where N is the size of the first dimension. So I would guess that [,] is faster on initial allocation.
Access is probably about the same, except that [][] would involve one extra dereference. Unless you're in an exceptionally tight loop it's probably a wash. Now, if you're doing something like image processing where you are referencing between rows rather than traversing row by row, locality of reference will play a big factor and [,] will probably edge out [][] depending on your cache size.
As Marc Gravell mentioned, usage is key to evaluating the performance...
It really depends. The MSDN Magazine article, Harness the Features of C# to Power Your Scientific Computing Projects, says this:
Although rectangular arrays are generally superior to jagged arrays in terms of structure and performance, there might be some cases where jagged arrays provide an optimal solution. If your application does not require arrays to be sorted, rearranged, partitioned, sparse, or large, then you might find jagged arrays to perform quite well.
type[,] will work faster. Not only because of less offset calculations. Mainly because of less constraint checking, less memory allocation and greater localization in memory. type[][] is not a single object -- it's 1 + N objects that must be allocated and can be away from each other.

Categories