Page 1 of 1

Basic Parallel.For 101 Rate Topic: -----

#1 modi123_1  Icon User is online

  • Suitor #2
  • member icon



Reputation: 9392
  • View blog
  • Posts: 35,273
  • Joined: 12-June 08

Posted 20 August 2011 - 11:18 AM

*
POPULAR

Threading - it's always a pain in the rear when you need to run it, but damn if the results aren't amazing when it gets going!

With the new 4.0 framework threading and parallelism has skyrocketed into a new height and become even easier for developers to access.

In this tutorial I'll be explaining the new "Parallel.For" loop. At it's heart, each iteration of the loop spawns a thread for some process to run on. Take one long sequential series of operations and break them into chunks so they can run at the same time!

Required:
4.0 framework

Threading Background:
When your application runs it creates a thread on your computer to execute. A dedicated process line that exists while your application is running. This is usually fine but sometimes you can lock up your application as some intensive task is processing. Usually the symptom is your application "hangs" or goes into a "not responding" state.

To avoid that from happening you can create new threads that branch off from your application, off load the process on their own time, and it won't gum up your main branch. No more hanging!

Additionally you can do things like crunch series of numbers - at the same time - and get the results faster. It's pretty nifty.

Think of it as branches coming off a tree trunk. When the thread processing is done the thread closes. There's a host of problems that can occur when threading (problems talking to each other, finishing at different times, etc), so it is best to read further before you decide to implement threading.

http://msdn.microsof...v=vs.71%29.aspx

This tutorial:
In this tutorial I'll show you two examples of parallel.for in action. The first is a simple race between threads. If you run it a few times you can see the threads do not all start or end at the same time.

The second tutorial is a simplified version of a problem I had to tackle recently. I had a very large record set to process so I created a small class to access, process, and save records between a given set of IDs. This cut the application time down considerably.

In this instance I am just adding numbers between ranges. The idea is if you find the ranges up front, feed that to your class, you should be able to cut down the processing time.

The parallel.for has a few ways of running, but the simplest is the way illustrated here.

Parallel.For(start_value, ending_value, delegate routine)


Much like how a regular for loop goes from a starting point to an ending point that concept is the same. What differs is instead of sequentially working (and waiting) through the body of the for loop - the parallel.for creates a thread to process the body (aka the delegate routine) in parallel! As fast as the parallel.for loop can create threads for each iteration is as fast as the parallel threads can start!

Required imports
Imports System.Threading
Imports System.Threading.Tasks


I created a small 'dummy class' that houses my two processing functions. This just highlights how you can encapsulate your logic in objects in a clean and efficient manner.

Dummy class
Spoiler


Example 1
        '-- ----------- Example 1 ----------- 
        '-- A holder for the five names that will signify our five threads.
        Dim sNames As String() = {"A", "B", "C", "D", "E"}

        '-- Invoke the name, the starting position, the ending position, and a delegate sub that is your parallel.for's "body".
        '-- i is the counter for 0 to sname.
        Parallel.For(0, sNames.Count, Sub(i)
                                          Dim temp As New Dummy(sNames(i)) '-- Create an instance of our dummy class with a string name.
                                          temp.Process() '-- start the processing.
                                      End Sub)



Example 2
        '-- ----------- Example 2 ----------- 
        '-- In this example I want the sum of each value between 1 and 1000000.  I'll break this problem down into intervals, feed them to a class to process, and run it in parallel!
        '-- This very well could be used for crunching similar chunks of data, scanning blocks of IP addresses, or calculating the next generation in a genetic algorithm.
        Dim myT As New Stopwatch() '-- start a timer to see how fast this takes.
        Dim lTotal As Int64 = 0 '-- our output bucket
        Dim lReturedVal As Int64 = 0

        Dim lStart As Int32 = 1 '-- the value to start counting in.
        Dim lInterval As Int32 = 1000000 '-- intervals

        Dim lIntervalHolder As New List(Of Int32) '-- Up front work to get our descrete intervals.

        Console.WriteLine("Create our intervals")
        For i As Int32 = 1 To sNames.Count '-- avoid any over lap!
            lIntervalHolder.Add(lStart)
            lStart += lInterval + 1
            lIntervalHolder.Add(lStart - 1)
        Next

        Console.WriteLine("Display our intervals")
        For i As Int32 = 0 To lIntervalHolder.Count - 1
            Console.WriteLine(lIntervalHolder(i))
        Next
        Console.WriteLine("--------------------------------")
        Console.WriteLine("Parallel count")

        myT.Start()

        Parallel.For(0, sNames.Count, Sub(i)
                                          Dim temp As New Dummy(sNames(i)) '-- Create an instance of our dummy class with a string name.
                                          lReturedVal = temp.Process2(lIntervalHolder(i * 2), lIntervalHolder(i * 2 + 1)) '-- start the processing.
                                          lTotal += lReturedVal   '-- add the returned total to the general total.
                                      End Sub)

        myT.Stop()
        Console.WriteLine(String.Format("Parallel total: {0}", lTotal))
        Console.WriteLine(myT.Elapsed)

        Console.WriteLine("--------------------------------")
        Dim lRegular As Int64 = 0
        Console.WriteLine("regular count")


        myT = Stopwatch.StartNew
        For i As Int32 = lIntervalHolder(0) To lIntervalHolder(lIntervalHolder.Count - 1)
            lRegular += i
        Next
        myT.Stop()
        Console.WriteLine(String.Format("regular total: {0}", lRegular))
        Console.WriteLine(myT.Elapsed)


Example of output:
Spoiler


Full code
Spoiler

Advanced topics to explore:
Implement this with data access and record processing
Try breaking out a long sequential math calculation!
Explore having your threads "talk" to each other.

Additional reading:
http://msdn.microsof...y/dd728073.aspx
http://msdn.microsof...y/dd470426.aspx
http://msdn.microsof...rallel.for.aspx
http://msdn.microsof...y/dd460703.aspx
http://msdn.microsof...e/cc163340.aspx
http://msdn.microsof...y/dd505035.aspx

Similar tutorials:
The Background Worker
Tasks (>= .net 4.0)

Is This A Good Question/Topic? 5
  • +

Replies To: Basic Parallel.For 101

#2 raziel_  Icon User is offline

  • Like a lollipop
  • member icon

Reputation: 465
  • View blog
  • Posts: 4,255
  • Joined: 25-March 09

Posted 20 August 2011 - 02:14 PM

Great tutorial!!!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1