1 #include "universe.h"
2 #include <tbb/task_scheduler_init.h>
3 #include <tbb/flow_graph.h>
4 #include <tbb/partitioner.h>
5 #include <tbb/blocked_range.h>
6 #include <tbb/parallel_for.h>
7
8
9 struct UpdateStressBody {
10 Universe & u_;
UpdateStressBodyUpdateStressBody11 UpdateStressBody(Universe & u):u_(u){}
operator ()UpdateStressBody12 void operator()( const tbb::blocked_range<int>& range ) const {
13 u_.UpdateStress(Universe::Rectangle(0, range.begin(), u_.UniverseWidth-1, range.size()));
14 }
15 };
16
17 struct UpdateVelocityBody {
18 Universe & u_;
UpdateVelocityBodyUpdateVelocityBody19 UpdateVelocityBody(Universe & u):u_(u){}
operator ()UpdateVelocityBody20 void operator()( const tbb::blocked_range<int>& y_range ) const {
21 u_.UpdateVelocity(Universe::Rectangle(1, y_range.begin(), u_.UniverseWidth-1, y_range.size()));
22 }
23 };
24
25
26 // the wavefront computation
seismic_tbb(unsigned num_threads,unsigned num_frames,Universe & u)27 void seismic_tbb(unsigned num_threads, unsigned num_frames, Universe& u) {
28
29 using namespace tbb;
30 using namespace tbb::flow;
31
32 tbb::task_scheduler_init init(num_threads);
33
34 static tbb::affinity_partitioner affinity;
35
36 for(unsigned i=0u; i<num_frames; ++i ) {
37 u.UpdatePulse();
38 tbb::parallel_for(tbb::blocked_range<int>( 0, u.UniverseHeight-1 ), // Index space for loop
39 UpdateStressBody(u), // Body of loop
40 affinity); // Affinity hint
41 tbb::parallel_for(tbb::blocked_range<int>( 1, u.UniverseHeight ), // Index space for loop
42 UpdateVelocityBody(u), // Body of loop
43 affinity); // Affinity hint
44 }
45 }
46
measure_time_tbb(unsigned num_threads,unsigned num_frames,Universe & u)47 std::chrono::microseconds measure_time_tbb(unsigned num_threads, unsigned num_frames, Universe& u) {
48 auto beg = std::chrono::high_resolution_clock::now();
49 seismic_tbb(num_threads, num_frames, u);
50 auto end = std::chrono::high_resolution_clock::now();
51 return std::chrono::duration_cast<std::chrono::microseconds>(end - beg);
52 }
53
54
55