|
Parallel processing is supposed to increase performance, not decrease.
Am I missing something??? Any explanations for slower parallel performance.
(I have a Intel core2 duo processor with 2 CPU’s. System.Environment.ProcessorCount = 2)
Thanks
Tiju
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ParallelConsole
{
class Program
{
static bool IsPrime(double x)
{
if (x < 2) return false;
double sqrroot = Math.Ceiling(Math.Sqrt(x));
bool isPrime = true;
for (int i = 2; i <= sqrroot; i++)
{
if (x % i == 0)
{
isPrime = false;
break;
}
}
return isPrime;
}
static void helper(double i, DateTime dt)
{
if (i != 1)
i = 3;
while (i > 0 && i <= 100000)
{
if (IsPrime(i))
Console.WriteLine(i.ToString() + " : " + DateTime.Now.Subtract(dt).ToString());
i += 4;
}
}
static void Main(string[] args)
{
Console.WriteLine("Finding prime numbers(from 1.). Press Enter to start!");
Console.ReadLine();
DateTime startTimeSequential; TimeSpan sq = new TimeSpan();
DateTime startTimeParallel; TimeSpan prl = new TimeSpan();
startTimeSequential = DateTime.Now;
for (int i = 1; i <= 2; i++)
{
helper(i, startTimeSequential);
}
sq = DateTime.Now.Subtract(startTimeSequential);
startTimeParallel = DateTime.Now;
Parallel.For(1, 3, (i => { helper(i, startTimeParallel); }));
prl = DateTime.Now.Subtract(startTimeParallel);
Console.WriteLine("Total time sequential = " + sq.ToString());
Console.WriteLine("Total time parallel (2) = " + prl.ToString());
Console.ReadLine();
}
}
}
|
|
|
|
|
tijujohn83 wrote: Parallel processing is supposed to increase performance, not decrease.
Am I missing something???
Yup, you're missing the piece of information that states that threads need to be created before they execute code. Look at it as if each thread was an application; each app needs be started, needs resources, needs handling.. that's all overhead.
Threads are used to divide the work over multiple cores, if there's much work to do (anything that takes longer than a second, according to MS design guidelines)
Try copying large files from the methods, you'll find that the second thread can work on the second core, without having to wait for thread 1 I are Troll
|
|
|
|
|
hmm. you are right. I was just trying out the parallel loops in the Task process library in .net 4
and while i was trying out different things, i ran the test again, and this time the parallel version run much faster.
|
|
|
|
|
You've run into the little problem of overhead and you've approached your problem incorrectly.
First, finding the primes of the first 100000 integers takes far less time than setting up the range partitioner (by default on IList and arrays) and grabbing an extra thread out of the pool to run your code.
You've also parallelized the outside loop that runs two (3 in this case) copies of the 1 through 100000 range instead of parallelizing the range itself. What you've done is really just forced this into a Task situtation and used Parallel to do it. This is not what Parallel was designed for.
It should look more like:
var primes = from c in Enumerable.Range(1, 10000000).AsParallel Select IsPrime(c)
Sorry, if this doesn't really compile, I'm translating from VB.NET to C# having never done LINQ in C#.
|
|
|
|
|
thanks for the comments. i'll try this out.
i have one doubt,
the two streams would be like
1,5,9,13,17,...
3,7,11,15,19...
how is this different from parallelizing the range.
|
|
|
|
|
Using your code as a base, this is how I would rewrite it. Note I threw together the custom IEnumerator<int> for an enumerable ForStep. I didn't see a "steppable" version in Enumerable or Parallel anywhere, so I threw together my own. Just a reminder, these LINQ queries are not executed until the variables Prime1 and Prime3 are used.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace IsPrime
{
class Program
{
static void Main(string[] args)
{
Stopwatch sw = new Stopwatch();
var Primes1 = from x in EnumerableForEach.ForEach(1, 10000000, 4).AsParallel()
where IsPrime(x)
select x;
var Primes3 = from x in EnumerableForEach.ForEach(3, 10000000, 4).AsParallel()
where IsPrime(x)
select x;
sw.Start();
Console.WriteLine("Primes (1, step 4) collection size: {0}", Primes1.Count());
sw.Stop();
Console.WriteLine("Time: {0}\n", sw.Elapsed);
sw = Stopwatch.StartNew();
Console.WriteLine("Primes (3, step 4) collection size: {0}", Primes3.Count());
sw.Stop();
Console.WriteLine("Time: {0}", sw.Elapsed);
}
static bool IsPrime(int x)
{
if (x < 2) return false;
double sqrRoot = Math.Ceiling(Math.Sqrt(x));
bool isPrime = true;
for (int i = 2; i < sqrRoot; i++)
{
if (x % i == 0)
{
isPrime = false;
break;
}
}
return isPrime;
}
}
}
public class EnumerableForEach
{
public static IEnumerable<int> ForEach(int start, int limit, int step)
{
return new EnumerableForEach.ForEachIterator(start, limit, step);
}
private sealed class ForEachIterator: IEnumerable<int>, IEnumerator<int>, IDisposable
{
int _start;
int _limit;
int _step;
int _current;
public ForEachIterator(int start, int limit, int step)
{
_start = start;
_limit = limit;
_step = step;
_current = start - step;
}
public IEnumerator<int> GetEnumerator()
{
return this;
}
IEnumerator IEnumerable.GetEnumerator()
{
return this;
}
public int Current()
{
return _current;
}
public void Dispose()
{
}
object IEnumerator.Current
{
get { return _current; }
}
public bool MoveNext()
{
_current += _step;
return (_current < _limit);
}
public void Reset()
{
throw new NotImplementedException();
}
int IEnumerator<int>.Current
{
get { return _current; }
}
}
}
The results I got on a 2 core VM (VMWare) running Windows Server 2003, through 10,000,000 instead of 100,000. Remove the .AsParallel() lines to force these LINQ's to run single threaded.
Primes (1, step 4) collection size: 332625
Time: 00:00:05.4500960
Primes (3, step 4) collection size: 332398
Time: 00:00:05.1003926
Press any key to continue . . .
|
|
|
|
|
Hi Tiju,
I can't speak to you specific question but I'm about to embark on a parallel project myself. I'm studying the Intel Concurrent Collections for C++. MSVC 2010 has some new stuff to support this also but my understanding is much of it is based on Intel technology.
Good Luck!
Rob.
|
|
|
|
|
Why are you using doubles to calculate prime numbers when primes are all integers?
If it's just so you can use the square root - there is no rule saying you can't cast that back to an int, and even better, it's possible to calculate the integer square root.
And you don't even need the square root (which is slow to calculate) anyway, you could compare the square of i with x (which is obviously equivalent to comparing i with the square root of x ) - better yet, you don't even need to do the multiplication (you can use repeated adding of odd numbers)
Also, after testing whether x is even (if ((x&1)==0) ) you never need to put an even number into the trial division ever again since if i divides x and i is even, 2 also divides x .
And you're already applying parallelisation? It's a good thing this is just a test..
|
|
|
|
|
There is more to it.
All primes except 2 and 3 are of the form multiple-of-6 plus or minus 1, so the two threads should be devoted to those two series, i.e. the increment needs to be 6, not 4 so multiples of 3 aren't even considered (I agree, they would fall out pretty quickly).
And then all that fancy enumerator stuff is costing cycles; its overhead well exceeds its functionality. A cleanly coded single thread can completely outpace what has been shown. I have a primes workbench where I experiment a lot, it currently locates all primes up to 10 million in 0.25 seconds; and up to 1 billion in 6.8 seconds.
Eventually I will write a little article on it!
|
|
|
|
|
Or you could use one of those fancy sieves.. but then you're changing the whole algorithm of course (cheat)
But yea write that article, you've been talking about for over half a year (IIRC)
|
|
|
|
|
I'm still researching, and making progress...
|
|
|
|
|
Fair enough, but it's the only article I'm really looking forward to reading
|
|
|
|
|
That is too bad, as I am planning some articles on other topics too...
|
|
|
|
|
|
I have a whole list of topics, all in various stages.
I plan to publish around ten articles on CP this year.
The one I like most myself is about the dynamics of ThreadPool. It will have some nice graphs!
And the biggest undertaking may be a series about P/Invoke.
|
|
|
|
|
That sounds pretty interesting as well.. ok.. maybe I'm looking forward to more than 1 article
|
|
|
|
|
Yeah, I just threw it together based on his code. It was by no means meant to be a tutorial on the most efficient way to do this. It just demonstrated a concept is all. Also, the performance numbers on that machine, well, suck, because it is a virtual running on a host that sucks at running VM's. I'm not allowed to put VS2010 on a real machine around here yet.
|
|
|
|
|
Fair enough. The concept and your code is interesting, it is just the example is a bit unfortunate.
I am looking forward to the official release of .NET 4.0 so I can investigate how it works, and how it compares to the manual approach.
|
|
|
|
|
I've been playing with the RC on that VM for about a week now. It's really cool to finally get to toy around with Tasks and Parallel. But, truthfully, the custom enumerator I threw together came from toying around with Enumberable.Range. It only uses integer and the results it returns can be no longer than integers. So, I tried throwing a custom Range method that supported Long's together and that's what I adapted to quickly come up with that example. I took his point to be that he was trying to figure out how the PTL worked. So...
I'm very interested in seeing an article on the Prime Sieve you've got. It would be interesting to see if it could be adapted to use or work with PTL.
|
|
|
|
|
It probably will be a few more months before my article on primes gets finished.
I can tell you right now the parallel stuff will not be useful for it, multi-threading hardly helps at all here. The first step in my analysis is proving calculations are so fast (assuming a sieve) the job is bandwidth limited, not compute bound. So I optimized it with banding (locality of reference, cache efficiency), all on a single thread. Only then I set out to figure a way to get extra cores involved, and there hardly is any. IIRC a second thread yields no more than a few percents of extra speed, taking care of some initialization, as running the sieve itself is an inherently sequential operation.
|
|
|
|
|
Hi,
i need to get only title, author and lenght of mp3 file, how i can do this??
please help me!
|
|
|
|
|
You need to read id3 tags from the file.
|
|
|
|
|
|
A little researc using this information[^] should speed you on your way. txtspeak is the realm of 9 year old children, not developers. Christian Graus
|
|
|
|
|
|