5

I can change my loop

for (int i = 0; i < something; i++)

to:

Parallel.For(0, something, i =>

But how to do this with this loop?:

for (i = 3; i <= something / 2; i = i + 2)

Thanks for answers.

Tamir Vered
  • 10,187
  • 5
  • 45
  • 57
Monna L
  • 105
  • 7

3 Answers3

9

Since

for (int i = 3; i <= something / 2; i = i + 2)
{
    ...
}

can be rewritten into

for (int k = 1; k < (something + 2) / 4; ++k)
{
    int i = 1 + 2 * k;
    ...
}

you can put

Parallel.For(1, (something + 2) / 4, k =>
{
    int i = 1 + 2 * k; 
    ... 
});
Tamir Vered
  • 10,187
  • 5
  • 45
  • 57
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
3

The third parameter is a delegate. So every iteration you could specify what your indexing variable shall do inside the delegate.

EDIT: Ok found a working solution: As already suggested by Dmitry Bychenko you should still start from 0 and just add the startValue as an offset

int something = 16;

int startValue = 3;
int stepSize = 2;

List<int> numbers = Enumerable.Range(0, 20).ToList();

Parallel.For(0, something / 2, i => 
{
    int ind = (stepSize * i) + startValue ; Console.WriteLine(numbers[ind]);
});
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
  • 1
    This doesn't do what he asks. your code runs for the values 5, 6, 7, 8, 9 in parallel, while he wants it to be equivalent to the loop which skips every second item (values: 3, 5, 7). – Tamir Vered Dec 01 '16 at 15:46
  • Note that changing `i` inside the `delegate` doesn't change the `Parallel.For` count and it's only a copied value type - `int`. – Tamir Vered Dec 01 '16 at 15:48
  • Don't you mean: `var numbers = Enumerable.Range(0, 20).Where(i => i % 2 == 0).ToList();` `Parallel.For(i => { Console.WriteLine(i); });` – ilivewithian Dec 01 '16 at 15:53
  • @ilivewithian this does not solve the problem. The OP had in mind to write the correct For-loop and not fiddle with the data. – Mong Zhu Dec 01 '16 at 15:55
  • @TamirVered thank you for pointing out the workings of `i`. It really was enlighting – Mong Zhu Dec 01 '16 at 16:20
1

Dmitry Bychenko's answer get it but you could also implement your own ParallelFor with custom step which will make your code somewhat more readable:

static void ParallelFor(int start, int last, Func<int, int> step, Action<int> action)
{
    var enumerable = StepEnumerable<int>
        .Create(start, step)
        .TakeWhile(x => x < last);

    Parallel.ForEach(enumerable, action);
}

Here is StepEnumerable's implementation:

public class StepEnumerator<T> : IEnumerator<T>
{
    ...

    public StepEnumerable(T value, Func<T, T> manipulation)
    {
        mEnumerator = new StepEnumerator<T>(value, manipulation);
    }

    public static StepEnumerable<T> Create(T value, Func<T, T> manipulation)
    {
        return new StepEnumerable<T>(value, manipulation);
    }

    ...
}

public class StepEnumerator<T> : IEnumerator<T>
{
    public bool MoveNext()
    {
        Current = mManipulation(Current);
        return true;
    }
}

Then, for example, if you run the following code:

ParallelFor(3, 16, x => x + 2, Console.WriteLine);

You'll get the following output (In separate lines of course):

5, 11, 7, 13, 9, 15

Tamir Vered
  • 10,187
  • 5
  • 45
  • 57