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