PFUNC 1.0
|
00001 #ifndef PFUNC_PARALLEL_FOR_HPP 00002 #define PFUNC_PARALLEL_FOR_HPP 00003 00004 #include <pfunc/pfunc.hpp> 00005 #include <iostream> 00006 00007 namespace pfunc { 00008 00028 template <typename PFuncInstanceType /*type of PFunc instantiated*/, 00029 typename ForExecutable/*type of the function*/, 00030 typename SpaceType /*type of the space*/> 00031 struct parallel_for : pfunc::virtual_functor { 00032 public: 00033 typedef typename PFuncInstanceType::taskmgr TaskMgrType; 00034 typedef typename PFuncInstanceType::task TaskType; 00035 00036 private: 00037 SpaceType space; 00038 const ForExecutable& func; 00039 TaskMgrType& taskmgr; 00040 00041 public: 00050 parallel_for (SpaceType space, 00051 const ForExecutable& func, 00052 TaskMgrType& taskmgr) : space(space), 00053 func(func), 00054 taskmgr (taskmgr) {} 00055 00056 void operator() (void) { 00057 if (space.can_split ()) { 00058 // Split into subspaces. 00059 typename SpaceType::subspace_container subspaces = space.split (); 00060 assert (1<=SpaceType::arity); 00061 00062 // Create a vector of tasks for each subspace but the first one. 00063 const int num_tasks = SpaceType::arity-1; 00064 TaskType subspace_tasks [num_tasks]; 00065 parallel_for<PFuncInstanceType, ForExecutable, SpaceType>* 00066 subspace_parallel_fors [num_tasks]; 00067 00068 // Save the first task to execute yourself, but do this last. 00069 typename SpaceType::subspace_container::iterator first=subspaces.begin(); 00070 space = *first++; 00071 00072 // Iterate and launch the tasks 00073 int task_index = 0; 00074 while (first != subspaces.end()) { 00075 subspace_parallel_fors [task_index] = new 00076 parallel_for<PFuncInstanceType, ForExecutable, SpaceType> 00077 (*first++, func, taskmgr); 00078 pfunc::spawn (taskmgr, // the task manager to use 00079 subspace_tasks[task_index], // task handle 00080 *(subspace_parallel_fors[task_index])); 00081 ++task_index; 00082 // the subspace for this comptn 00083 } 00084 00085 (*this)(); // executing this loop ourselves. 00086 00087 // Wait for completion of other tasks 00088 pfunc::wait_all (taskmgr, // the task manager to use 00089 subspace_tasks, // beginning 00090 subspace_tasks+num_tasks); // end 00091 00092 // Delete the subspace_parallel_fors 00093 for (int i=0; i<num_tasks; ++i) delete subspace_parallel_fors[i]; 00094 } else { 00095 // No more splitting --- simply invoke the function on the given space. 00096 func (space); 00097 } 00098 } 00099 }; 00100 00101 } // namespace pfunc 00102 00103 #endif // PFUNC_PARALLEL_FOR_HPP