Custom Loop with Arbitrary Initialization, Condition, and Update

Custom Loop with Arbitrary Initialization, Condition, and Update

  • Comments 5

The Parallel.For loop construct provided by Parallel Extensions is focused on providing a parallel alternative to the common sequential pattern of a for loop that iterates over a range of numbers.  However, the for loop construct in a language like C# is not limited just to numbers and iterating over ranges.  It supports arbitrary initialization, condition, and update expressions, for example:

for(var i = init(); cond(i); i = upd(i)) { Use(i); }

There isn't any built-in Parallel construct that supports this pattern. However, one of our goals with Parallel Extensions is to provide the foundational support to add these types of constructs easily on top of what we do provide.  This is a good example of that.  Consider the following implementation:

public static void ParallelFor<T>(
    Func<T> init, Func<T,bool> cond, Func<T,T> upd, Action<T> body)
{
    Parallel.ForEach(Iterate(init, cond, upd), body); 
}

private static IEnumerable<T> Iterate<T>(
    Func<T> init, Func<T,bool> cond, Func<T,T> upd)
{
    for(var i=init(); cond(i); i = upd(i)) yield return i;
}

As you can see, it was straightforward to create a parallel For method that accepted arbitrary initialization, condition, and update expressions.  This was done by creating an iterator in C# for looping as was done in the original sequential example, and then passing the result of an invocation of that iterator to a call to Parallel.ForEach.  We can now use this construct.  For example, let's say I have a linked list of nodes, and I want to execute some substantial amount of code for every node in the list.  Sequentially, that might look like:

for(Node n = list; n != null; n = n.Next)
{
    Process(n);
}

With our new ParallelFor method, we can do the same thing in parallel:

ParallelFor(() => list, n => n != null, n => n.Next, n =>
{
    Process(n);
});

Simplicity.  Of course, there are many other ways the ParallelFor method could be implemented; building on top of Parallel.ForEach is just one of them.

Leave a Comment
  • Please add 5 and 3 and type the answer here:
  • Post
  • Hi there,

    i just remembered what i was missing lately using parallel.for:

    how about an override which allows for LONG indexes instead of INT. Yes, the current workaround is to use a cast, but that's ... ;)

  • Pointernil, thanks for the request.  Support for In64 in Parallel.For is certainly something we're considering.  What are you doing that you need Int64s?  Is it that you are already using Int64 values but in the range of Int32 and are just trying to avoid a cast, or are you actually outside the bounds of what an Int32 can support?

  • @toub: 1) my index being typed with Long sneaked in by using FileStream.Seek method with large, sorry hudge files; this one takes a "long Offset" param;

    2) PFX rocks!

    3) Please have a serious talk with Anders or Mr.Erik Meijers ;) and have them wrap the lib with some syntactic sugar in the compilers.

    4) When are you guys going to announce that OS level interface to co-processing units and the PFX support for that? ;)

  • Pointernil, thanks for the feedback, and I'm very glad you find Parallel Extensions useful.  We're definitely considering Int64 support; others have suggested it's important, too.

    As for Anders and Erik, we talk with them all the time :)

  • I am very much looking forward to the new .Net Parallel extensions being RTM&#39;d. This Post from Stephen

Page 1 of 1 (5 items)