ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AstSharedMemoryParallelProcessingImpl.h
Go to the documentation of this file.
1 // Author: Gergo Barany
2 // $Id: AstSharedMemoryParallelProcessing.C,v 1.1 2008/01/08 02:56:38 dquinlan Exp $
3 
4 #ifndef ASTSHAREDMEMORYPARALLELPROCESSING_C
5 #define ASTSHAREDMEMORYPARALLELPROCESSING_C
6 
7 // tps (01/08/2010) Added sage3basic since this doesnt compile under gcc4.1.2
8 //#include "sage3basic.h"
9 //#include "sage3.h"
10 
11 // DQ (3/20/2009): Trying to fix error on Cygwin platform.
12 #ifdef _MSC_VER
13 #pragma message ("Error: pthread.h is unavailable on MSVC, we might want to use boost.thread library.")
14 #else
15 #include <pthread.h>
16 #endif
17 
19 
20 // Throughout this file, I is the InheritedAttributeType, S is the
21 // SynthesizedAttributeType -- the type names are still horrible
22 
23 // parallel TOP DOWN BOTTOM UP implementation
24 
25 template <class I, class S>
32  visitedNodes(0), runningParallelTraversal(false),
33  synchronizationWindowSize(syncInfo.synchronizationWindowSize)
34 {
35 }
36 
37 template <class I, class S>
38 void
40 {
42 }
43 
44 template <class I, class S>
49 {
51  {
52  synchronize();
53  visitedNodes = 0;
54  }
55 
56  // let the superclass handle actual attribute evaluation
57  return Superclass::evaluateInheritedAttribute(astNode, inheritedValues);
58 }
59 
60 template <class I, class S>
63 {
64  // delegate the call to the superclass
66 
67  // signal that we are done
69  {
70  signalFinish();
71  // clear the flag so subsequent traversals can be non-parallel
73  }
74 }
75 
76 // This class holds the arguments to a traversal thread: The parallelizable
77 // traversal class that contains a number of traversals, the node to start the
78 // traversal from, and the list of initial inherited values.
79 template <class I, class S>
81 {
85 
90  : traversal(traversal), basenode(basenode), inheritedValues(inheritedValues)
91  {
92  }
93 };
94 
95 // This is the function that is executed in each thread. It basically unpacks
96 // its arguments and starts the traversal on them; the traversal's final
97 // result is returned. Synchronization is built into the parallelizable
98 // processing classes.
99 template <class I, class S>
101 {
103 
105  SgNode *basenode = threadArgs->basenode;
107  *inheritedValues = threadArgs->inheritedValues;
108  delete threadArgs;
109 
110  // Set the flag that indicates that this is indeed a parallel traversal;
111  // it is cleared by the traversal class itself when it is done.
112  traversal->set_runningParallelTraversal(true);
113  // Start the traversal.
114  return traversal->traverse(basenode, inheritedValues);
115 }
116 
117 template <class I, class S>
120  SgNode *basenode,
122 {
123  // GB (09/27/2007): Is this really required? Inheritance of templated classes is just weird.
124  const typename Superclass::TraversalPtrList &traversals = Superclass::traversals;
125 
126  size_t numberOfTraversals = traversals.size();
127  size_t i;
128 
129  AstSharedMemoryParallelProcessingSynchronizationInfo syncInfo(numberOfThreads, synchronizationWindowSize);
130 
131  // Chop the flat list of traversals apart and distribute them into a few
132  // parallelizable traversals.
133  ParallelizableTraversalPtrList parallelTraversals(numberOfThreads);
134  std::vector<InheritedAttributeTypeList *> parallelInheritedValues(numberOfThreads);
135  size_t begin = 0, end;
136  for (i = 0; i < numberOfThreads; i++)
137  {
138  end = begin + numberOfTraversals / numberOfThreads;
139  if (end > numberOfTraversals)
140  end = numberOfTraversals;
141 
142  parallelTraversals[i]
144  std::vector<TraversalPtr>(traversals.begin() + begin, traversals.begin() + end));
145  parallelInheritedValues[i]
147  inheritedValues->begin() + begin, inheritedValues->begin() + end);
148  begin = end;
149  }
150 
151 #ifndef _MSC_VER
152  // Start a thread for each of the parallelizable traversals with its share
153  // of the initial inherited attributes.
154  pthread_t *threads = new pthread_t[numberOfThreads];
155  for (i = 0; i < numberOfThreads; i++)
156  {
157  pthread_create(&threads[i], NULL,
158  parallelTopDownBottomUpProcessingThread<I, S>,
160  parallelTraversals[i], basenode, parallelInheritedValues[i]));
161  }
162 
163  // Main "event loop" for the "master" thread: Simply wait for the
164  // condition that is signalled when a thread is completely done with its
165  // traversal. The counter tells us when we are finished.
166  pthread_mutex_lock(syncInfo.mutex);
167  while (*syncInfo.finishedThreads < numberOfThreads)
168  pthread_cond_wait(syncInfo.threadFinishedEvent, syncInfo.mutex);
169  pthread_mutex_unlock(syncInfo.mutex);
170 
171  // Grab the results from each traversal.
172  std::vector<SynthesizedAttributeTypeList *> finalResults(numberOfThreads);
173  for (i = 0; i < numberOfThreads; i++)
174  pthread_join(threads[i], (void **) &finalResults[i]);
175  delete threads;
176 #endif
177 
178  // Flatten the nested list of traversal results.
180  for (i = 0; i < numberOfThreads; i++)
181  std::copy(finalResults[i]->begin(), finalResults[i]->end(), std::back_inserter(*flatFinalResults));
182 
183  // Done! Return the final results.
184  return flatFinalResults;
185 }
186 
187 template <class I, class S>
189  : numberOfThreads(2), synchronizationWindowSize(100000)
190 {
191 }
192 
193 template <class I, class S>
196  : AstCombinedTopDownBottomUpProcessing<I, S>(traversals), numberOfThreads(2), synchronizationWindowSize(100000)
197 {
198 }
199 
200 template <class I, class S>
201 void
203 {
204 #if !USE_ROSE
205 // DQ (11/3/2011): EDG compilains about this (but GNU allowed it, I think that EDG might be correct
206 // since it is a private variable. But since we are only trying to compile ROSE with ROSE (using the
207 // new EDG 4.3 front-end as a tests) we can just skip this case for now.
208  numberOfThreads = threads;
209 #endif
210 }
211 
212 template <class I, class S>
213 void
215 {
216 #if !USE_ROSE
217 // DQ (11/3/2011): EDG compilains about this (but GNU allowed it, I think that EDG might be correct
218 // since it is a private variable. But since we are only trying to compile ROSE with ROSE (using the
219 // new EDG 4.3 front-end as a tests) we can just skip this case for now.
220  synchronizationWindowSize = windowSize;
221 #endif
222 }
223 
224 // parallel TOP DOWN implementation
225 
226 template <class I>
233  visitedNodes(0), runningParallelTraversal(false),
234  synchronizationWindowSize(syncInfo.synchronizationWindowSize)
235 {
236 }
237 
238 template <class I>
239 void
241 {
243 }
244 
245 template <class I>
250 {
252  {
253  synchronize();
254  visitedNodes = 0;
255  }
256 
257  // let the superclass handle actual attribute evaluation
258  return Superclass::evaluateInheritedAttribute(astNode, inheritedValues);
259 }
260 
261 template <class I>
264 {
265  // delegate the call to the superclass
267 
268  // signal that we are done
270  {
271  signalFinish();
272  // clear the flag so subsequent traversals can be non-parallel
273  runningParallelTraversal = false;
274  }
275 }
276 
277 // This class holds the arguments to a traversal thread: The parallelizable
278 // traversal class that contains a number of traversals, the node to start the
279 // traversal from, and the list of initial inherited values.
280 template <class I>
282 {
286 
289  SgNode *basenode,
291  : traversal(traversal), basenode(basenode), inheritedValues(inheritedValues)
292  {
293  }
294 };
295 
296 // This is the function that is executed in each thread. It basically unpacks
297 // its arguments and starts the traversal on them; the traversal's final
298 // result is returned. Synchronization is built into the parallelizable
299 // processing classes.
300 template <class I>
302 {
304 
306  SgNode *basenode = threadArgs->basenode;
308  *inheritedValues = threadArgs->inheritedValues;
309  delete threadArgs;
310 
311  // Set the flag that indicates that this is indeed a parallel traversal;
312  // it is cleared by the traversal class itself when it is done.
313  traversal->set_runningParallelTraversal(true);
314  // Start the traversal.
315  traversal->traverse(basenode, inheritedValues);
316 
317  // Need to return something.
318  return NULL;
319 }
320 
321 template <class I>
322 void
324  SgNode *basenode,
326 {
327  const typename Superclass::TraversalPtrList &traversals = Superclass::traversals;
328 
329  size_t numberOfTraversals = traversals.size();
330  size_t i;
331 
332  AstSharedMemoryParallelProcessingSynchronizationInfo syncInfo(numberOfThreads, synchronizationWindowSize);
333 
334  // Chop the flat list of traversals apart and distribute them into a few
335  // parallelizable traversals.
336  ParallelizableTraversalPtrList parallelTraversals(numberOfThreads);
337  std::vector<InheritedAttributeTypeList *> parallelInheritedValues(numberOfThreads);
338  size_t begin = 0, end;
339  for (i = 0; i < numberOfThreads; i++)
340  {
341  end = begin + numberOfTraversals / numberOfThreads;
342  if (end > numberOfTraversals)
343  end = numberOfTraversals;
344 
345  parallelTraversals[i]
347  std::vector<TraversalPtr>(traversals.begin() + begin, traversals.begin() + end));
348  parallelInheritedValues[i]
350  inheritedValues->begin() + begin, inheritedValues->begin() + end);
351  begin = end;
352  }
353 
354  // Start a thread for each of the parallelizable traversals with its share
355  // of the initial inherited attributes.
356  pthread_t *threads = new pthread_t[numberOfThreads];
357  for (i = 0; i < numberOfThreads; i++)
358  {
359  pthread_create(&threads[i], NULL,
360  parallelTopDownProcessingThread<I>,
362  parallelTraversals[i], basenode, parallelInheritedValues[i]));
363  }
364 
365  // Main "event loop" for the "master" thread: Simply wait for the
366  // condition that is signalled when a thread is completely done with its
367  // traversal. The counter tells us when we are finished.
368  pthread_mutex_lock(syncInfo.mutex);
369  while (*syncInfo.finishedThreads < numberOfThreads)
370  pthread_cond_wait(syncInfo.threadFinishedEvent, syncInfo.mutex);
371  pthread_mutex_unlock(syncInfo.mutex);
372 
373  // Grab the results from each traversal.
374  std::vector<void *> finalResults(numberOfThreads);
375  for (i = 0; i < numberOfThreads; i++)
376  pthread_join(threads[i], &finalResults[i]);
377  delete threads;
378 
379  // Done!
380 }
381 
382 template <class I>
384  : numberOfThreads(2), synchronizationWindowSize(100000)
385 {
386 }
387 
388 template <class I>
391  : AstCombinedTopDownProcessing<I>(traversals), numberOfThreads(2), synchronizationWindowSize(100000)
392 {
393 }
394 
395 template <class I>
396 void
398 {
399 #if !USE_ROSE
400 // DQ (11/3/2011): EDG compilains about this (but GNU allowed it, I think that EDG might be correct
401 // since it is a private variable. But since we are only trying to compile ROSE with ROSE (using the
402 // new EDG 4.3 front-end as a tests) we can just skip this case for now.
403  numberOfThreads = threads;
404 #endif
405 }
406 
407 template <class I>
408 void
410 {
411 #if !USE_ROSE
412 // DQ (11/3/2011): EDG compilains about this (but GNU allowed it, I think that EDG might be correct
413 // since it is a private variable. But since we are only trying to compile ROSE with ROSE (using the
414 // new EDG 4.3 front-end as a tests) we can just skip this case for now.
415  synchronizationWindowSize = windowSize;
416 #endif
417 }
418 
419 // parallel BOTTOM UP implementation
420 
421 template <class S>
428  visitedNodes(0), runningParallelTraversal(false),
429  synchronizationWindowSize(syncInfo.synchronizationWindowSize)
430 {
431 }
432 
433 template <class S>
434 void
436 {
438 }
439 
440 template <class S>
445 {
447  {
448  synchronize();
449  visitedNodes = 0;
450  }
451 
452  // let the superclass handle actual attribute evaluation
453  return Superclass::evaluateSynthesizedAttribute(astNode, synthesizedAttributes);
454 }
455 
456 template <class S>
459 {
460  // delegate the call to the superclass
462 
463  // signal that we are done
465  {
466  signalFinish();
467  // clear the flag so subsequent traversals can be non-parallel
468  runningParallelTraversal = false;
469  }
470 }
471 
472 // This class holds the arguments to a traversal thread: The parallelizable
473 // traversal class that contains a number of traversals, and the node to start the
474 // traversal from.
475 template <class S>
477 {
480 
483  SgNode *basenode)
484  : traversal(traversal), basenode(basenode)
485  {
486  }
487 };
488 
489 // This is the function that is executed in each thread. It basically unpacks
490 // its arguments and starts the traversal on them; the traversal's final
491 // result is returned. Synchronization is built into the parallelizable
492 // processing classes.
493 template <class S>
495 {
497 
499  SgNode *basenode = threadArgs->basenode;
500  delete threadArgs;
501 
502  // Set the flag that indicates that this is indeed a parallel traversal;
503  // it is cleared by the traversal class itself when it is done.
504  traversal->set_runningParallelTraversal(true);
505  // Start the traversal.
506  return traversal->traverse(basenode);
507 }
508 
509 template <class S>
512 {
513  const typename Superclass::TraversalPtrList &traversals = Superclass::traversals;
514 
515  size_t numberOfTraversals = traversals.size();
516  size_t i;
517 
518  AstSharedMemoryParallelProcessingSynchronizationInfo syncInfo(numberOfThreads, synchronizationWindowSize);
519 
520  // Chop the flat list of traversals apart and distribute them into a few
521  // parallelizable traversals.
522  ParallelizableTraversalPtrList parallelTraversals(numberOfThreads);
523  size_t begin = 0, end;
524  for (i = 0; i < numberOfThreads; i++)
525  {
526  end = begin + numberOfTraversals / numberOfThreads;
527  if (end > numberOfTraversals)
528  end = numberOfTraversals;
529 
530  parallelTraversals[i]
532  std::vector<TraversalPtr>(traversals.begin() + begin, traversals.begin() + end));
533  begin = end;
534  }
535 
536  // Start a thread for each of the parallelizable traversals.
537  pthread_t *threads = new pthread_t[numberOfThreads];
538  for (i = 0; i < numberOfThreads; i++)
539  {
540  pthread_create(&threads[i], NULL,
541  parallelBottomUpProcessingThread<S>,
543  parallelTraversals[i], basenode));
544  }
545 
546  // Main "event loop" for the "master" thread: Simply wait for the
547  // condition that is signalled when a thread is completely done with its
548  // traversal. The counter tells us when we are finished.
549  pthread_mutex_lock(syncInfo.mutex);
550  while (*syncInfo.finishedThreads < numberOfThreads)
551  pthread_cond_wait(syncInfo.threadFinishedEvent, syncInfo.mutex);
552  pthread_mutex_unlock(syncInfo.mutex);
553 
554  // Grab the results from each traversal.
555  std::vector<SynthesizedAttributeTypeList *> finalResults(numberOfThreads);
556  for (i = 0; i < numberOfThreads; i++)
557  pthread_join(threads[i], (void **) &finalResults[i]);
558  delete threads;
559 
560  // Flatten the nested list of traversal results.
562  for (i = 0; i < numberOfThreads; i++)
563  std::copy(finalResults[i]->begin(), finalResults[i]->end(), std::back_inserter(*flatFinalResults));
564 
565  // Done! Return the final results.
566  return flatFinalResults;
567 }
568 
569 template <class S>
571  : numberOfThreads(2), synchronizationWindowSize(100000)
572 {
573 }
574 
575 template <class S>
578  : AstCombinedBottomUpProcessing<S>(traversals), numberOfThreads(2), synchronizationWindowSize(100000)
579 {
580 }
581 
582 template <class S>
583 void
585 {
586 #if !USE_ROSE
587 // DQ (11/3/2011): EDG compilains about this (but GNU allowed it, I think that EDG might be correct
588 // since it is a private variable. But since we are only trying to compile ROSE with ROSE (using the
589 // new EDG 4.3 front-end as a tests) we can just skip this case for now.
590  numberOfThreads = threads;
591 #endif
592 }
593 
594 template <class S>
595 void
597 {
598 #if !USE_ROSE
599 // DQ (11/3/2011): EDG compilains about this (but GNU allowed it, I think that EDG might be correct
600 // since it is a private variable. But since we are only trying to compile ROSE with ROSE (using the
601 // new EDG 4.3 front-end as a tests) we can just skip this case for now.
602  synchronizationWindowSize = windowSize;
603 #endif
604 }
605 
606 #endif