Parallel. For C #

I am trying to convert the following Collatz hypothesis 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;
        }
    } 

Use .NET 4.0 Parallel.For instead:

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 that I'm not too far from him, the famous last words.

Thanks in advance.

+5
source share
1 answer

Your problem is that you do not want to use Parallel.Forin this case, because you already have an array ( nums) to iterate that calls Parallel.ForEach. However, your array is created using Enumerable.Range, and you are not actually using it for anything, so the best way to do this is with AsParallelLINQ (PLINQ):

public static class CollatzConjexture2
{
    public static int Calculate(int StartIndex, int MaxSequence)
    {
        var nums = Enumerable.Range(StartIndex, MaxSequence);
        return nums.AsParallel()
                    // compute length of chain for each number
                   .Select(n => new { key = n, len = CollatzChainLength(n) })
                    // find longest chain
                   .Aggregate((max, cur) => cur.len > max.len ||
                    // make sure we have lowest key for longest chain
                      max.len == cur.len && cur.key < max.key ? cur : max)
                    // get number that produced longest chain
                   .key;
    }

    private static int CollatzChainLength(Int64 Number)
    {
        int chainLength;
        for (chainLength = 1; Number != 1; chainLength++)
            Number = (Number & 1) == 0 ? Number >> 1 : Number * 3 + 1;
        return chainLength;
    }
}

, . , , inline, , . . x64 x86 .

+9