7

I want to convert a for loop which increments the iterator by 2 every pass into a Parallel For loop using the TPL. The data is not order dependent or constrained in any way, but I only want to process the data in every other element of my source array (which is _Datalist in the code below), hence the need to increment by 2.

My For Loop:

for (int i = 1; i < _DataList.Length - 1; i += 2)
{
     // Do work for _DataList[i]
}

Is it possible to tell the parallel loop that I want to increment i by two instead of one?

Here's the Parallel Loop, but obviously i is only incrementing by 1 each iteration:

        Task.Factory.StartNew(() =>
            Parallel.For(1, _DataList.Length, i =>
            {
                // do work for _DataList[i]                    
            })
        );

I could tell the inner loop body to ignore odd values of i, but that seems a litle messy - is there a way of doing it in the loop initialisation somehow?

Gareth
  • 2,746
  • 4
  • 30
  • 44

4 Answers4

12

You can halve the number of steps and double the indices:

Parallel.For(0, _DataList.Length / 2, i =>
{
    // do work for _DataList[2 * i]                    
});
dtb
  • 213,145
  • 36
  • 401
  • 431
11

How about:

var odds = Enumerable.Range(1, _DataList.Length).Where(i => i % 2 != 0);

Task.Factory.StartNew(() =>
    Parallel.ForEach(odds, i =>
    {
        // do work for _DataList[i]                    
    })
);
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
1

Darin Dimitrov's answer shows an easy way to accomplish this.

However, this wasn't added, as it's typically a sign that the loop bodies aren't truly distinct. In most cases, the need to use a different increment value typically only comes with the need for processing in a specific order or other concerns that will cause parallelization to create race conditions.

Community
  • 1
  • 1
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Noted for future reference, but in the case to which I'm applying this loop the processing order of the elements is really not a concern – Gareth Oct 20 '10 at 17:40
  • @Gareth: I just mention this since there was actually a discussion (which I can't find atm) by Stephen Toub mentioning specifically why Parallel.For didn't add this feature - and it basically came down to it typically is problematic for parallel processing, but you can always work around it via a partitioner or parallel.foreach. – Reed Copsey Oct 20 '10 at 17:44
  • I believe this use case comes up very naturally when working with SIMD instructions in .NET, since they operate by creating a `Vector<'T>` for each nth element of an array, where N is the width of the vector. You can't leverage Parallel.For for small vectorized functions because the enumerator or multiplication tricks defeat the perf benefit. – jackmott Jul 26 '16 at 17:06
0

Just skip even values.

Task.Factory.StartNew(() =>
                Parallel.For(1, _DataList.Length, i =>
                {
                    if(i % 2 == 0)
                    {
                        // do work for   
                    }   
                })
            );
Junior
  • 21
  • 2
  • 1
    Can you explain more about your answer? It's usually considered good practice to give some information or explanation for the answers you give. This may help future users or OP more. – Bono Sep 19 '15 at 09:25
  • This is not a good idea as you're creating overhead and is what I was trying to avoid - see the first comment on the question. Fortunately there were some good solutions 5 years ago :) – Gareth Sep 21 '15 at 08:07