Let's say I have these two methods:
public BigInteger PFactorial(int n)
{
return Enumerable.Range(1, n)
.AsParallel()
.Select(i => (BigInteger)i)
.Aggregate(BigInteger.One, BigInteger.Multiply);
}
public BigInteger Factorial(int n)
{
BigInteger result = BigInteger.One;
for(int i = 1; i <= n; i++)
result *= i;
return result;
}
The following were the results I got:
PFactorial(25000) -> 0,9897 seconds
Factorial(25000) -> 0,9252 seconds
I understand that PLINQ has some overhead because of the threads setup, but with such a big n
I was expecting PLINQ to be faster.
Here is another result:
PFactorial(50000) -> 4,91035 seconds
Factorial(50000) -> 4,40056 seconds
Parallel is not really possible with aggregate. At least i cant imagine that in my mind. Any way, You should make parallelization possible by dividing your list into chunks. Find those results. and finally multiply chunks. Here is the fast way of PLinq.
static public BigInteger PFactorial(int n)
{
var range = Enumerable.Range(1, n).Select(x => (BigInteger) x).AsParallel();
var lists = range.GroupBy(x => x/(n/Environment.ProcessorCount)).Select(x => x.AsEnumerable());
var results = lists.Select(x => x.Aggregate(BigInteger.One, BigInteger.Multiply));
var result = results.Aggregate(BigInteger.One, BigInteger.Multiply);
return result;
}
Test
PFactorial(50000) -> 1,41 seconds
Factorial(50000) -> 2,69 seconds
Edit: As mentioned by Servy and Chatzigiannakis if you dont use seed it can perfectly use parallelization and you get pretty much same results as above (a bit faster).
return Enumerable.Range(1,n).Select(x => (BigInteger)x).AsParallel().Aggregate(BigInteger.Multiply);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With