From 141929f63f765de4d7e4618cb5a622ac72a93c84 Mon Sep 17 00:00:00 2001 From: Bruno Turcksin Date: Tue, 22 Oct 2013 15:21:37 +0000 Subject: [PATCH] Use tbb::task instead of Thread in step-13 and step-14. git-svn-id: https://svn.dealii.org/trunk@31385 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/examples/step-13/step-13.cc | 91 ++++++++++++++++++++++++----- deal.II/examples/step-14/step-14.cc | 75 +++++++++++++++++++++--- 2 files changed, 144 insertions(+), 22 deletions(-) diff --git a/deal.II/examples/step-13/step-13.cc b/deal.II/examples/step-13/step-13.cc index d2b2693b4b..17abbb2d79 100644 --- a/deal.II/examples/step-13/step-13.cc +++ b/deal.II/examples/step-13/step-13.cc @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -57,6 +56,11 @@ #include #include +#ifdef DEAL_II_WITH_THREADS +# include +# include +#endif + // The last step is as in all previous programs: namespace Step13 { @@ -64,6 +68,7 @@ namespace Step13 namespace Assembler { + // Dummy structure struct Scratch { Scratch() {} @@ -643,7 +648,7 @@ namespace Step13 // various subobjects, and there is a function that implements a // conjugate gradient method as solver. private: - struct LinearSystem + struct LinearSystem { LinearSystem (const DoFHandler &dof_handler); @@ -655,6 +660,53 @@ namespace Step13 Vector rhs; }; +#ifdef DEAL_II_WITH_THREADS + + // Tasks in TBB must be derived from tbb::task and override tbb::task* + // execute. + // The purpose of HangingNodeTask is to apply execute DoFTools::make_hanging_node_constraints. + struct HangingNodeTask : public tbb::task + { + HangingNodeTask (const DoFHandler &dof_handler,ConstraintMatrix &hanging_node_constraints) : + dof_handler(&dof_handler), + hanging_node_constraints(& hanging_node_constraints) {} + + tbb::task* execute() + { + DoFTools::make_hanging_node_constraints(*dof_handler,*hanging_node_constraints); + + return NULL; + } + + const DoFHandler* dof_handler; + ConstraintMatrix* hanging_node_constraints; + }; + + + + // The purpose of SparsityPatternTask is to create the sparsity pattern. + struct SparsityPatternTask : public tbb::task + { + SparsityPatternTask (const DoFHandler &dof_handler,SparsityPattern &sparsity_pattern) : + dof_handler(&dof_handler), + sparsity_pattern(&sparsity_pattern) {} + + tbb::task* execute() + { + sparsity_pattern->reinit (dof_handler->n_dofs(), + dof_handler->n_dofs(), + dof_handler->max_couplings_between_dofs()); + DoFTools::make_sparsity_pattern (*dof_handler, *sparsity_pattern); + + return NULL; + } + + const DoFHandler* dof_handler; + SparsityPattern* sparsity_pattern; + }; + +#endif + // Finally, there is a pair of functions which will be used to assemble // the actual system matrix. It calls the virtual function assembling // the right hand side, and installs a number threads each running the @@ -920,23 +972,36 @@ namespace Step13 { hanging_node_constraints.clear (); - void (*mhnc_p) (const DoFHandler &, - ConstraintMatrix &) - = &DoFTools::make_hanging_node_constraints; - - Threads::Thread<> - mhnc_thread = Threads::new_thread (mhnc_p, - dof_handler, - hanging_node_constraints); +#ifdef DEAL_II_WITH_THREADS + tbb::task_scheduler_init init; + // Create an empty task to be the parent of the two tasks that we need. + tbb::empty_task* empty_task = new (tbb::task::allocate_root()) tbb::empty_task; + // Set the reference count to 3 (number of children+1 because + // wati_for_all returns when ref_count is one). + empty_task->set_ref_count(3); + + HangingNodeTask* hanging_node_task = + new (empty_task->allocate_child()) HangingNodeTask(dof_handler,hanging_node_constraints); + SparsityPatternTask* sparsity_pattern_task = + new (empty_task->allocate_child()) SparsityPatternTask(dof_handler,sparsity_pattern); + + // Spawn the two tasks + empty_task->spawn(*hanging_node_task); + empty_task->spawn(*sparsity_pattern_task); + + // Wait for children to finish + empty_task->wait_for_all(); + // empty_task must be destroy manually because it does not return. + empty_task->destroy(*empty_task); +#else + DoFTools::make_hanging_node_constraints(dof_handler,hanging_node_constraints); sparsity_pattern.reinit (dof_handler.n_dofs(), dof_handler.n_dofs(), dof_handler.max_couplings_between_dofs()); DoFTools::make_sparsity_pattern (dof_handler, sparsity_pattern); +#endif - // Wait until the hanging_node_constraints object is fully - // set up, then close it and use it to condense the sparsity pattern: - mhnc_thread.join (); hanging_node_constraints.close (); hanging_node_constraints.condense (sparsity_pattern); diff --git a/deal.II/examples/step-14/step-14.cc b/deal.II/examples/step-14/step-14.cc index 575dfe9469..ec777aa8ce 100644 --- a/deal.II/examples/step-14/step-14.cc +++ b/deal.II/examples/step-14/step-14.cc @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -55,6 +54,11 @@ #include #include +#ifdef DEAL_II_WITH_THREADS +# include +# include +#endif + // The last step is as in all previous programs: namespace Step14 { @@ -488,6 +492,47 @@ namespace Step14 Vector rhs; }; +#ifdef DEAL_II_WITH_THREADS + + struct HangingNodeTask : public tbb::task + { + HangingNodeTask (const DoFHandler &dof_handler,ConstraintMatrix &hanging_node_constraints) : + dof_handler(&dof_handler), + hanging_node_constraints(& hanging_node_constraints) {} + + tbb::task* execute() + { + DoFTools::make_hanging_node_constraints(*dof_handler,*hanging_node_constraints); + + return NULL; + } + + const DoFHandler* dof_handler; + ConstraintMatrix* hanging_node_constraints; + }; + + struct SparsityPatternTask : public tbb::task + { + SparsityPatternTask (const DoFHandler &dof_handler,SparsityPattern &sparsity_pattern) : + dof_handler(&dof_handler), + sparsity_pattern(&sparsity_pattern) {} + + tbb::task* execute() + { + sparsity_pattern->reinit (dof_handler->n_dofs(), + dof_handler->n_dofs(), + dof_handler->max_couplings_between_dofs()); + DoFTools::make_sparsity_pattern (*dof_handler, *sparsity_pattern); + + return NULL; + } + + const DoFHandler* dof_handler; + SparsityPattern* sparsity_pattern; + }; + +#endif + void assemble_linear_system (LinearSystem &linear_system); @@ -677,21 +722,33 @@ namespace Step14 { hanging_node_constraints.clear (); - void (*mhnc_p) (const DoFHandler &, - ConstraintMatrix &) - = &DoFTools::make_hanging_node_constraints; +#ifdef DEAL_II_WITH_THREADS + tbb::task_scheduler_init init; + // Create an empty task to be the parent of the two tasks that we need. + tbb::empty_task* empty_task = new (tbb::task::allocate_root()) tbb::empty_task; + // Set the reference count to 3 (number of children+1) + empty_task->set_ref_count(3); + + HangingNodeTask* hanging_node_task = + new (empty_task->allocate_child()) HangingNodeTask(dof_handler,hanging_node_constraints); + SparsityPatternTask* sparsity_pattern_task = + new (empty_task->allocate_child()) SparsityPatternTask(dof_handler,sparsity_pattern); + + empty_task->spawn(*hanging_node_task); + empty_task->spawn(*sparsity_pattern_task); - Threads::Thread<> - mhnc_thread = Threads::new_thread (mhnc_p, - dof_handler, - hanging_node_constraints); + // Wait for children to finish + empty_task->wait_for_all(); + empty_task->destroy(*empty_task); +#else + DoFTools::make_hanging_node_constraints(dof_handler,hanging_node_constraints); sparsity_pattern.reinit (dof_handler.n_dofs(), dof_handler.n_dofs(), dof_handler.max_couplings_between_dofs()); DoFTools::make_sparsity_pattern (dof_handler, sparsity_pattern); +#endif - mhnc_thread.join (); hanging_node_constraints.close (); hanging_node_constraints.condense (sparsity_pattern); -- 2.39.5