1 // =============================================================================
2 // === spqr_parallel ===========================================================
3 // =============================================================================
4
5 // Factorize all the tasks in parallel with TBB.
6 // The GPU is not used.
7
8 #ifdef HAVE_TBB
9 #include "spqr.hpp"
10 #include <tbb/task_scheduler_init.h>
11 #include <tbb/task.h>
12
13 using namespace tbb ;
14
15 // =============================================================================
16 // === spqr_zippy ==============================================================
17 // =============================================================================
18
19 template <typename Entry> class spqr_zippy: public task
20 {
21 public:
22
23 // -------------------------------------------------------------------------
24 // spqr_zippy state
25 // -------------------------------------------------------------------------
26
27 const Long id ;
28 spqr_blob <Entry> *Blob ;
29
30 // -------------------------------------------------------------------------
31 // spqr_zippy constructor
32 // -------------------------------------------------------------------------
33
spqr_zippy(Long id_,spqr_blob<Entry> * Blob_)34 spqr_zippy (Long id_, spqr_blob <Entry> *Blob_) : id (id_), Blob (Blob_) { }
35
36 // -------------------------------------------------------------------------
37 // spqr_zippy task
38 // -------------------------------------------------------------------------
39
execute()40 task* execute ( )
41 {
42
43 // ---------------------------------------------------------------------
44 // spawn my children
45 // ---------------------------------------------------------------------
46
47 Long *TaskChildp = Blob->QRsym->TaskChildp ;
48 Long *TaskChild = Blob->QRsym->TaskChild ;
49 Long pfirst = TaskChildp [id] ;
50 Long plast = TaskChildp [id+1] ;
51 Long nchildren = plast - pfirst ;
52
53 if (nchildren > 0)
54 {
55 // create a list of TBB tasks, one for each child
56 task_list TasksToDo ;
57 for (Long i = 0 ; i < nchildren ; i++)
58 {
59 Long child = TaskChild [pfirst+i] ;
60 TasksToDo.push_back (*new (allocate_child ( ))
61 spqr_zippy (child, Blob)) ;
62 }
63 // spawn all children and wait for all of them to finish
64 set_ref_count (nchildren + 1) ;
65 spawn_and_wait_for_all (TasksToDo) ;
66 }
67
68 // ---------------------------------------------------------------------
69 // chilren are done, do my own task
70 // ---------------------------------------------------------------------
71
72 spqr_kernel (id, Blob) ;
73
74 return (NULL) ;
75 }
76 } ;
77
78
79 // =============================================================================
80 // === spqr_parallel ===========================================================
81 // =============================================================================
82
spqr_parallel(Long ntasks,int nthreads,spqr_blob<Entry> * Blob)83 template <typename Entry> void spqr_parallel
84 (
85 Long ntasks,
86 int nthreads,
87 spqr_blob <Entry> *Blob
88 )
89 {
90 // fire up TBB on the task tree, starting at the root id = ntasks-1
91 task_scheduler_init
92 init (nthreads <= 0 ? (task_scheduler_init::automatic) : nthreads) ;
93 spqr_zippy <Entry> & a = *new (task::allocate_root ( ))
94 spqr_zippy <Entry> (ntasks-1, Blob) ;
95 task::spawn_root_and_wait (a) ;
96 }
97
98 // =============================================================================
99
100 template void spqr_parallel <double>
101 (
102 Long ntasks,
103 int nthreads,
104 spqr_blob <double> *Blob
105 ) ;
106
107 template void spqr_parallel <Complex>
108 (
109 Long ntasks,
110 int nthreads,
111 spqr_blob <Complex> *Blob
112 ) ;
113
114 #endif
115