Grand Central Dispatch Programming

Joined
Aug 10, 2010
Messages
1
Reaction score
0
Points
1
Hi Guys,

I have a question on using Grand Central Dispatch.

I am using GCD to parallelize a for loop. However, I am summing up the result from each iteration of the for loop. The summing up portion is the critical section. I can succesfully parallelize the for loop using dispatch_apply. But, I am unable to figure out how to correctly implement the critical section. Below is the baseline code and GCD based code. Can you help?

Base code:

for (i=0;i<= num_steps; i++)
{
x = (i+0.5)*step;
sum = sum + 4.0/(1.0+x*x);
}
pi = step * sum;
printf("The value of pi is %f\n", pi);

Code written Using GCD:

dispatch_queue_t theQueue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply (num_steps, theQueue, ^ (size_t i)
{
double x, pi, sum = 0.0;
step = 1.0/(double) num_steps;
x = (i+0.5)*step;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),
^{
double sum;
sum = sum + 4.0/(1.0+x*x);

});
pi = step * sum;
printf("The value of pi is %f\n", pi);
});

Thanks a bunch.

Regards,
Hema
 
Joined
Jun 25, 2005
Messages
3,231
Reaction score
112
Points
63
Location
On the road
Your Mac's Specs
2011 MBP, i7, 16GB RAM, MBP 2.16Ghz Core Duo, 2GB ram, Dual 867Mhz MDD, 1.75GB ram, ATI 9800 Pro vid
You had several problems with the code you posted, but I'm only going to talk about why you had trouble with sum.

First, the sum variable has to be placed outside the dispatch and declared with the __block keyword. This allows altering that variable from within the block. Also, given its new placement, you can now use it to get pi after the threading is complete.

Second, using the sum variable for an assignment to another variable before all threads have completed will likely return an invalid number because it hasn't had the final result assigned to it yet. To avoid that, look at the group functions I used.

Third, notice the new sumQueue. I used that because some other info I found suggested that it was good practice in this case, to not use the default queue. I quick check showed the default queue also works. So I'm not sure what is best.


Code:
void doFixed()
{
    NSLog(@"doFixed");
	
	NSInteger num_steps = 314;
	
	dispatch_queue_t theQueue = dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
	dispatch_queue_t sumQueue = dispatch_queue_create("com.example.sum", NULL);
	dispatch_group_t asyncGroup = dispatch_group_create();
	
	__block double sum = 0.0;
	double step = 1.0/(double) num_steps;
	double pi;
			
	dispatch_apply (num_steps, theQueue, ^ (size_t i) 
	{
		double x;
		x = (i+0.5)*step;
		dispatch_group_async( asyncGroup, sumQueue,
					   ^{
					   sum = sum + 4.0/(1.0+x*x);	
					   });

	});
	dispatch_group_wait(asyncGroup, DISPATCH_TIME_FOREVER);
	dispatch_release(sumQueue);

	pi = step * sum;
	printf("The value of pi is %f\n", pi);
}

By the way, when you post code, use the CODE wrapping tags, like I did. It makes it easier for people to read.
 

Shop Amazon


Shop for your Apple, Mac, iPhone and other computer products on Amazon.
We are a participant in the Amazon Services LLC Associates Program, an affiliate program designed to provide a means for us to earn fees by linking to Amazon and affiliated sites.
Top