I am trying convert the following Collatz Conjecture algorithm from:
public class CollatzConjexture
{
public static int Calculate(int StartIndex, int MaxSequence)
{
int ChainLength = 0;
int key = 0;
bool ContinuteCalulating = true;
int LongestChain = 0;
Int64 Remainder = 0;
for (int i = StartIndex; i <= MaxSequence; i++)
{
ChainLength = 1;
Remainder = i;
ContinuteCalulating = true;
while (ContinuteCalulating)
{
Remainder = CalculateCollatzConjecture(Remainder);
if (Remainder == 1)
ContinuteCalulating = false;
ChainLength += 1;
}
if (ChainLength > LongestChain)
{
LongestChain = ChainLength;
key = i;
}
}
return key;
}
private static Int64 CalculateCollatzConjecture(Int64 Number)
{
if (Number % 2 == 0)
return Number / 2;
else
return (3 * Number) + 1;
}
}
To instead use the .NET 4.0 Parallel.For :
int ChainLength = 0;
int key = 0;
bool ContinuteCalulating = true;
int LongestChain = 0;
Int64 Remainder = 0;
int[] nums = Enumerable.Range(1, 1500000).ToArray();
long total = 0;
// Use type parameter to make subtotal a long, not an int
Parallel.For<int>(1, nums.Length, () => 1, (j, loop, subtotal) =>
{
Remainder = j;
while (ContinuteCalulating)
{
Remainder = CalculateCollatzConjecture(Remainder);
if (Remainder == 1)
ContinuteCalulating = false;
ChainLength += 1;
}
if (ChainLength > LongestChain)
{
LongestChain = ChainLength;
key = j;
}
return key;
},
(x) => Interlocked.Add(ref key, x)
);
I have a feeling I’m not too far from it, famous last words.
Thanks in advance.
Your problem is that you don’t want to use
Parallel.Forin this instance because you already have an array (nums) to iterate over, which calls forParallel.ForEach. However, your array is created withEnumerable.Rangeand you don’t actually use it for anything, so the best way to do it is withAsParalleland LINQ (PLINQ):This method is about twice as fast on my computer as the serial implementation. Also note that I optimized the main loop so that it does the computation inline rather than calling a function and it uses bitwise math instead of multiplying and dividing. This made it about twice as fast again. Compiling it for x64 instead of x86 also made it more than twice as fast.