1. #include <iostream>
2. #include <algorithm>
3. #include <vector>
4. #include <list>
5. #include <math.h>
6. #include <tbb/task_scheduler_init.h>
7. #include <tbb/blocked_range.h>
8. #include <tbb/parallel_for.h>
9. #include <tbb/pipeline.h>
10. #include <tbb/tick_count.h>
11.
12.
13.
14.
15. template<class _Cat1, class _Cat2>
16. struct both_random_helper{
17. typedef std::forward_iterator_tag Iter_cat;
18. };
19. template<>
20. struct both_random_helper<
21. std::random_access_iterator_tag,
22. std::random_access_iterator_tag>{
23. typedef std::random_access_iterator_tag Iter_cat;
24. };
25.
26. template<class _InIt, class _OutIt>
27. struct Iter_pair{
28. _InIt m_in;
29. _OutIt m_out;
30. Iter_pair(_InIt _in, _OutIt _out)
31. :m_in(_in),m_out(_out){}
32.
33. Iter_pair operator+(size_t off) const
34. {
35. return Iter_pair(m_in+off, m_out+off);
36. }
37. size_t operator-(Iter_pair rhs) const
38. {
39. return m_in-rhs.m_in;
40. }
41. bool operator<(Iter_pair rhs) const
42. {
43. return m_in<rhs.m_in;
44. }
45. };
46.
47. template<class _InIt, class _OutIt, class _Fn1>
48. struct op_parallel_transform{
49. op_parallel_transform(_Fn1 _Func)
50. :m_Func(_Func){}
51. void operator()(const tbb::blocked_range<Iter_pair<_InIt,_OutIt> > &r) const
52. {
53. std::transform(r.begin().m_in, r.end().m_in, r.begin().m_out, m_Func);
54. }
55. private:
56. _Fn1 m_Func;
57. };
58. template<class _InIt, class _OutIt, class _Fn1>
59. _OutIt _parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func, std::random_access_iterator_tag)
60. {
61.
62. typedef typename Iter_pair<_InIt,_OutIt> iter_pair_type;
63. _OutIt LastDest = _Dest + (_Last - _First);
64. iter_pair_type begin(_First, _Dest);
65. iter_pair_type end(_Last, LastDest);
66. tbb::blocked_range<iter_pair_type> x(begin, end);
67. tbb::parallel_for(x, op_parallel_transform<_InIt,_OutIt,_Fn1>(_Func), tbb::auto_partitioner());
68. return LastDest;
69. }
70.
71. template<class _InIt>
72. struct filter_in : tbb::filter{
73. filter_in(_InIt _First, _InIt _Last)
74. :tbb::filter(true),m_First(_First), m_Last(_Last){}
75. void* operator()(void*)
76. {
77. if(m_First==m_Last) return NULL;
78. void* p = &(*m_First);
79. ++m_First;
80. return p;
81. }
82. private:
83. _InIt m_First, m_Last;
84. };
85. template<class _Fn1>
86. struct filter_process : tbb::filter{
87. typedef typename _Fn1::result_type r_type;
88. typedef typename _Fn1::argument_type a_type;
89. filter_process(_Fn1 _Func)
90. :tbb::filter(false),m_Func(_Func){}
91. void* operator()(void* data)
92. {
93. a_type &at = *(a_type*)data;
94. m_r = m_Func( at );
95. return &m_r;
96. }
97. private:
98. _Fn1 m_Func;
99. r_type m_r;
100. };
101. template<class _OutIt, class _DataType>
102. struct filter_out : tbb::filter{
103. filter_out(_OutIt _Dest)
104. :tbb::filter(true),m_Dest(_Dest){}
105. void* operator()(void* data)
106. {
107. _DataType *p = (_DataType*) data;
108. *m_Dest = *p;
109. ++m_Dest;
110. return NULL;
111. }
112. private:
113. _OutIt m_Dest;
114. };
115. template<class _InIt, class _OutIt, class _Fn1>
116. _OutIt _parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func, std::forward_iterator_tag)
117. {
118.
119. tbb::pipeline pipeline;
120. filter_in<_InIt> f1(_First, _Last);
121. filter_process<_Fn1> f2(_Func);
122. filter_out<_OutIt, _Fn1::result_type> f3(_Dest);
123. pipeline.add_filter(f1);
124. pipeline.add_filter(f2);
125. pipeline.add_filter(f3);
126. pipeline.run(3);
127. return _Dest;
128. }
129.
130. template<class _InIt, class _OutIt, class _Fn1>
131. inline
132. _OutIt parallel_transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func)
133. {
134. typedef typename std::iterator_traits<_InIt>::iterator_category cat1;
135. typedef typename std::iterator_traits<_OutIt>::iterator_category cat2;
136. return _parallel_transform(_First, _Last, _Dest, _Func, both_random_helper<cat1,cat2>::Iter_cat());
137. }
138.
139. struct SinFunctor
140. :std::unary_function<double, double>{
141. double operator()(double &d) const
142. {
143.
144. double sum = 0;
145. for(int i=0; i<10000; i++) sum += sin(i*d);
146. return sum;
147. }
148. };
149. int main()
150. {
151.
152. std::vector<double> a(10000,1.5);
153.
154. std::list<double> b(10000,1.5);
155. tbb::task_scheduler_init init;
156. tbb::tick_count t0,t1;
157. t0 = tbb::tick_count::now();
158. parallel_transform(a.begin(), a.end(), a.begin(), SinFunctor());
159. t1 = tbb::tick_count::now();
160. std::cout << "并行(随机迭代)" << (t1 - t0).seconds() << std::endl;
161.
162. t0 = tbb::tick_count::now();
163. std::transform(a.begin(), a.end(), a.begin(), SinFunctor());
164. t1 = tbb::tick_count::now();
165. std::cout << "原版(随机迭代)" << (t1 - t0).seconds() << std::endl;
166. t0 = tbb::tick_count::now();
167. parallel_transform(b.begin(), b.end(), b.begin(), SinFunctor());
168. t1 = tbb::tick_count::now();
169. std::cout << "并行(顺序迭代)" << (t1 - t0).seconds() << std::endl;
170. t0 = tbb::tick_count::now();
171. std::transform(b.begin(), b.end(), b.begin(), SinFunctor());
172. t1 = tbb::tick_count::now();
173. std::cout << "原版(顺序迭代)"<< (t1 - t0).seconds() << std::endl;
174.
175. std::cin.get();
176. return 0;
177. }