July 22, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Native Parallel Programming for Visual C++: State Management

  • June 2, 2009
  • By Nick Wienholt
  • Send Email »
  • More Articles »

At TechEd 2009, Microsoft announced the release of Beta 1 of Visual Studio 2010. This release contains a number of new features in the Parallel Programming Library (PPL) over the October 2008 CTP. In addition to some changes to task groups (covered in-depth previously), Visual Studio 2010 Beta 1 includes new state management functionality that simplifies multi-task development.

Task Group Cancellation

One of the new Beta 1 PPL features is the ability to cancel a running task group. Joining the run and wait method on the task_group type is a new cancel method. There is also a corresponding is_canceling method that you can use to check whether a cancelation is in progress. The task_group_status enumeration also has a new value called canceled that lets you check whether cancelation occurred. The following code demonstrates these new features:

//declare tasks and run tasks
task_group tg; 
tg.run(([]{printf("consoleWrite0\n");}));
tg.run(([]{printf("consoleWrite1\n");}));
//cancel tasks
tg.cancel();
//check whether tasks are being cancelled
bool taskGroupIsCanceling = tg.is_canceling();
//check on status of task group
task_group_status status = tg.wait();
if (status == completed){
   printf("Tasks were completed successfully\n");
}
else if (status == canceled){
   printf("Tasks were canceled during task execution\n");
}
else{
   printf("An exception occured during task execution\n");
}

Combinable

One of the most effective patterns to achieve the maximum benefit from executing programming tasks in parallel is for each parallel branch to work on a local copy or subset of the data being processed, and then combine the results when processing completes. This pattern minimizes resource contention, and eliminates the potential for deadlock and data inconsistency bugs that can occur when parallel threads attempt to update the same memory location.

There is nothing overly complex about using this pattern, but it can be tedious to code it manually for each use. To simplify pattern usage, Beta 1 of Visual C++ 2010 adds the combinable templated type. The template parameter passed to combinable is the type of the object that each task will operate on. The type must have both a default constructor and a copy constructor. Each task accesses its own copy of the combinable managed resource using the local method. After all tasks are complete, you can combine the results into a single result set using either the combine or combine_each method.

The following code adds elements to a vector using three separate tasks, and then combines the results into a single vector using both combination methods.

//declare a combinable vector of integers
combinable<vector<int>> v; 
//add an element to the vector using three separate tasks
parallel_invoke(
   [&]{ v.local().push_back(1); },                 
   [&]{ v.local().push_back(2); },                 
   [&]{ v.local().push_back(3); }
); 
//merge the task-local copies using combine_each
vector<int> result1;
v.combine_each(
   [&](vector<int>& local)
   {
      result1.insert(result1.end(), 
         local.begin(), local.end());
   }
);
//merge the task-local copies using combine
vector<int> result2 = v.combine(
   [](vector<int> left, vector<int> right)->vector<int>{    
      left.insert(left.end(), right.begin(), right.end());
      return left;
   });

Note the use of the explicit return type declaration in the lambda expression in the last code statement. The two statements inside the lambda expression prevent the compiler from correctly inferring the return type, so manual declaration is required.

It's possible to use combinable for types that do not have a default constructor (or in situations where the use of the default constructor is not appropriate) by using the combinable constructor, which takes a generator function that creates objects of the type of the template parameter. The first few lines of the preceding code sample are rewritten below using the overloaded generator constructor. In this case, the generator function returns a vector that already contains an element.

//declare a combinable vector of integers
combinable<vector<int>> v([]{return vector<int>(1, 0);});
					
Tags: Visual C++, C++, Parallelism



Page 1 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel