Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parallel.For using step != 1

Is there any way to achieve the Parallel.For version of this for loop?

for (int i = 0; i < 100; i += 2) { DoStuff(i); }

I don't see an overload which accepts a step parameter, though I can't think of any reason this would be logically impossible.

The accepted answer to this and this question suggests using Parallel.ForEach on a range of ints generated using Enumerable.Range, but in my case I am using thread local data so Parallel.ForEach is not an option.

Another option is to just check if i % 2 == 0 in the body of my loop and return, but this still executes the thread local data intializer Func and finalizer Func. Below is a code snippet demonstrating this option:

Parallel.For<Bar>(0, limit, 

    () => new Bar(), //thread local data initialize

    (i, state, local) => //loop body
    {
        if (i % 2 != 0) return local;
        local.foo += DoStuff(i);
        return local;
    },

    (local) => //thread local data post-action
    {
        lock (loopLocker)
        {
            globalData.foo += local.foo;
        );
    }
);
like image 606
Rotem Avatar asked Dec 26 '12 19:12

Rotem


2 Answers

Here's a hint:

for (int j = 0; j < 50; j++) { i = 2*j; DoStuff(); }

In general, see if you can figure out the number of iterations and a transformation from iteration number to the variable value.

like image 73
Ben Voigt Avatar answered Sep 29 '22 14:09

Ben Voigt


Here is another way to process stepped indexes

private void ParallelForEachProcessSteppedIndexes()
        {
            Parallel.ForEach(SteppedIterator(0, 100, 2), (index) => DoStuff(index));
        }

private static IEnumerable<int> SteppedIterator(int startIndex, int endIndex, int stepSize)
        {
            for (int i = startIndex; i < endIndex; i = i + stepSize)
            {
                yield return i;
            }
        }
like image 26
Toan Nguyen Avatar answered Sep 29 '22 14:09

Toan Nguyen