예제 #1
0
        /// <summary>
        /// Executes a for loop in which iterations may run in parallel.
        /// </summary>
        /// <param name="fromInclusive">The start index, inclusive.</param>
        /// <param name="toExclusive">The end index, exclusive.</param>
        /// <param name="rangeSize">The partition size for splitting work into smaller pieces.</param>
        /// <param name="body">The body to be invoked for each iteration range.</param>
        public static void For(int fromInclusive, int toExclusive, int rangeSize, Action <int, int> body)
        {
            if (body == null)
            {
                throw new ArgumentNullException("body");
            }
            if (fromInclusive < 0)
            {
                throw new ArgumentOutOfRangeException("fromInclusive");
            }
            if (fromInclusive > toExclusive)
            {
                throw new ArgumentOutOfRangeException("toExclusive");
            }
            if (rangeSize < 1)
            {
                throw new ArgumentOutOfRangeException("rangeSize");
            }

            var length = toExclusive - fromInclusive;

            // Special case: nothing to do
            if (length <= 0)
            {
                return;
            }

            // Special case: not worth to parallelize, inline
            if (Control.MaxDegreeOfParallelism < 2 || (rangeSize * 2) > length)
            {
                body(fromInclusive, toExclusive);
                return;
            }

            // Common case
            Parallel.ForEach(
                Partitioner.Create(fromInclusive, toExclusive, rangeSize),
                CreateParallelOptions(),
                range => body(range.Item1, range.Item2));
        }
예제 #2
0
        /// <summary>
        /// Selects an item (such as Max or Min).
        /// </summary>
        /// <param name="array">The array to iterate over.</param>
        /// <param name="select">The function to select items over a subset.</param>
        /// <param name="reduce">The function to select the item of selection from the subsets.</param>
        /// <returns>The selected value.</returns>
        public static TOut Aggregate <T, TOut>(T[] array, Func <int, T, TOut> select, Func <TOut[], TOut> reduce)
        {
            if (select == null)
            {
                throw new ArgumentNullException("select");
            }
            if (reduce == null)
            {
                throw new ArgumentNullException("reduce");
            }

            // Special case: no action
            if (array == null || array.Length == 0)
            {
                return(reduce(new TOut[0]));
            }

            // Special case: single action, inline
            if (array.Length == 1)
            {
                return(reduce(new[] { select(0, array[0]) }));
            }

            // Special case: straight execution without parallelism
            if (Control.MaxDegreeOfParallelism < 2)
            {
                var mapped = new TOut[array.Length];
                for (int k = 0; k < mapped.Length; k++)
                {
                    mapped[k] = select(k, array[k]);
                }
                return(reduce(mapped));
            }

            // Common case
            var intermediateResults = new List <TOut>();
            var syncLock            = new object();

            Parallel.ForEach(
                Partitioner.Create(0, array.Length),
                CreateParallelOptions(),
                () => new List <TOut>(),
                (range, loop, localData) =>
            {
                var mapped = new TOut[range.Item2 - range.Item1];
                for (int k = 0; k < mapped.Length; k++)
                {
                    mapped[k] = select(k + range.Item1, array[k + range.Item1]);
                }
                localData.Add(reduce(mapped));
                return(localData);
            },
                localResult =>
            {
                lock (syncLock)
                {
                    intermediateResults.Add(reduce(localResult.ToArray()));
                }
            });
            return(reduce(intermediateResults.ToArray()));
        }
예제 #3
0
        /// <summary>
        /// Selects an item (such as Max or Min).
        /// </summary>
        /// <param name="fromInclusive">Starting index of the loop.</param>
        /// <param name="toExclusive">Ending index of the loop</param>
        /// <param name="select">The function to select items over a subset.</param>
        /// <param name="reduce">The function to select the item of selection from the subsets.</param>
        /// <returns>The selected value.</returns>
        public static T Aggregate <T>(int fromInclusive, int toExclusive, Func <int, T> select, Func <T[], T> reduce)
        {
            if (select == null)
            {
                throw new ArgumentNullException("select");
            }
            if (reduce == null)
            {
                throw new ArgumentNullException("reduce");
            }

            // Special case: no action
            if (fromInclusive >= toExclusive)
            {
                return(reduce(new T[0]));
            }

            // Special case: single action, inline
            if (fromInclusive == (toExclusive - 1))
            {
                return(reduce(new[] { select(fromInclusive) }));
            }

            // Special case: straight execution without parallelism
            if (Control.MaxDegreeOfParallelism < 2)
            {
                var mapped = new T[toExclusive - fromInclusive];
                for (int k = 0; k < mapped.Length; k++)
                {
                    mapped[k] = select(k + fromInclusive);
                }
                return(reduce(mapped));
            }

            // Common case
            var intermediateResults = new List <T>();
            var syncLock            = new object();

            Parallel.ForEach(
                Partitioner.Create(fromInclusive, toExclusive),
                CreateParallelOptions(),
                () => new List <T>(),
                (range, loop, localData) =>
            {
                var mapped = new T[range.Item2 - range.Item1];
                for (int k = 0; k < mapped.Length; k++)
                {
                    mapped[k] = select(k + range.Item1);
                }
                localData.Add(reduce(mapped));
                return(localData);
            },
                localResult =>
            {
                lock (syncLock)
                {
                    intermediateResults.Add(reduce(localResult.ToArray()));
                }
            });
            return(reduce(intermediateResults.ToArray()));
        }