1 | /* |
2 | Copyright (c) 2005-2019 Intel Corporation |
3 | |
4 | Licensed under the Apache License, Version 2.0 (the "License"); |
5 | you may not use this file except in compliance with the License. |
6 | You may obtain a copy of the License at |
7 | |
8 | http://www.apache.org/licenses/LICENSE-2.0 |
9 | |
10 | Unless required by applicable law or agreed to in writing, software |
11 | distributed under the License is distributed on an "AS IS" BASIS, |
12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | See the License for the specific language governing permissions and |
14 | limitations under the License. |
15 | */ |
16 | |
17 | #define NOMINMAX |
18 | |
19 | #include "harness_defs.h" |
20 | #if __TBB_TEST_SKIP_LAMBDA |
21 | |
22 | #include "harness.h" |
23 | int TestMain() { |
24 | REPORT("Known issue: lambdas are not properly supported on the platform \n" ); |
25 | return Harness::Skipped; |
26 | } |
27 | |
28 | #else /*__TBB_TEST_SKIP_LAMBDA*/ |
29 | |
30 | #include "tbb/tbb.h" |
31 | #include "tbb/combinable.h" |
32 | #include <cstdio> |
33 | #include <list> |
34 | |
35 | using namespace std; |
36 | using namespace tbb; |
37 | |
38 | typedef pair<int,int> max_element_t; |
39 | |
40 | void f(int val, int *arr, int start, int stop) { |
41 | for (int i=start; i<=stop; ++i) { |
42 | arr[i] = val; |
43 | } |
44 | } |
45 | |
46 | #include "harness.h" |
47 | |
48 | #if __TBB_TASK_GROUP_CONTEXT |
49 | int Fib(int n) { |
50 | if( n<2 ) { |
51 | return n; |
52 | } else { |
53 | int x=0, y=0; |
54 | task_group g; |
55 | g.run( [&]{x=Fib(n-1);} ); // spawn a task |
56 | g.run( [&]{y=Fib(n-2);} ); // spawn another task |
57 | g.wait(); // wait for both tasks to complete |
58 | return x+y; |
59 | } |
60 | } |
61 | #endif /* !__TBB_TASK_GROUP_CONTEXT */ |
62 | |
63 | #include "harness_report.h" |
64 | #include "harness_assert.h" |
65 | |
66 | int TestMain () { |
67 | const int N = 1000; |
68 | const int Grainsize = N/1000; |
69 | int a[N]; |
70 | int max_sum; |
71 | ASSERT( MinThread>=1, "Error: Number of threads must be positive.\n" ); |
72 | |
73 | for(int p=MinThread; p<=MaxThread; ++p) { |
74 | task_scheduler_init init(p); |
75 | |
76 | REMARK("Running lambda expression tests on %d threads...\n" , p); |
77 | |
78 | //test parallel_for |
79 | REMARK("Testing parallel_for... " ); |
80 | parallel_for(blocked_range<int>(0,N,Grainsize), |
81 | [&] (blocked_range<int>& r) { |
82 | for (int i=r.begin(); i!=r.end(); ++i) a[i] = i; |
83 | }); |
84 | ASSERT(a[0]==0 && a[N-1]==N-1, "parallel_for w/lambdas failed.\n" ); |
85 | REMARK("passed.\n" ); |
86 | |
87 | //test parallel_reduce |
88 | REMARK("Testing parallel_reduce... " ); |
89 | int sum = parallel_reduce(blocked_range<int>(0,N,Grainsize), int(0), |
90 | [&] (blocked_range<int>& r, int current_sum) -> int { |
91 | for (int i=r.begin(); i!=r.end(); ++i) |
92 | current_sum += a[i]*(1000-i); |
93 | return current_sum; |
94 | }, |
95 | [] (const int x1, const int x2) { |
96 | return x1+x2; |
97 | } ); |
98 | |
99 | max_element_t max_el = |
100 | parallel_reduce(blocked_range<int>(0,N,Grainsize), make_pair(a[0], 0), |
101 | [&] (blocked_range<int>& r, max_element_t current_max) |
102 | -> max_element_t { |
103 | for (int i=r.begin(); i!=r.end(); ++i) |
104 | if (a[i]>current_max.first) |
105 | current_max = make_pair(a[i], i); |
106 | return current_max; |
107 | }, |
108 | [] (const max_element_t x1, const max_element_t x2) { |
109 | return (x1.first>x2.first)?x1:x2; |
110 | }); |
111 | ASSERT(sum==166666500 && max_el.first==999 && max_el.second==999, |
112 | "parallel_reduce w/lambdas failed.\n" ); |
113 | REMARK("passed.\n" ); |
114 | |
115 | //test parallel_do |
116 | REMARK("Testing parallel_do... " ); |
117 | list<int> s; |
118 | s.push_back(0); |
119 | |
120 | parallel_do(s.begin(), s.end(), |
121 | [&](int foo, parallel_do_feeder<int>& feeder) { |
122 | if (foo == 42) return; |
123 | else if (foo>42) { |
124 | s.push_back(foo-3); |
125 | feeder.add(foo-3); |
126 | } else { |
127 | s.push_back(foo+5); |
128 | feeder.add(foo+5); |
129 | } |
130 | }); |
131 | ASSERT(s.back()==42, "parallel_do w/lambda failed.\n" ); |
132 | REMARK("passed.\n" ); |
133 | |
134 | //test parallel_invoke |
135 | REMARK("Testing parallel_invoke... " ); |
136 | parallel_invoke([&]{ f(2, a, 0, N/3); }, |
137 | [&]{ f(1, a, N/3+1, 2*(N/3)); }, |
138 | [&]{ f(0, a, 2*(N/3)+1, N-1); }); |
139 | ASSERT(a[0]==2.0 && a[N-1]==0.0, "parallel_invoke w/lambda failed.\n" ); |
140 | REMARK("passed.\n" ); |
141 | |
142 | //test tbb_thread |
143 | REMARK("Testing tbb_thread... " ); |
144 | tbb_thread::id myId; |
145 | tbb_thread myThread([](int x, int y) { |
146 | ASSERT(x==42 && y==64, "tbb_thread w/lambda failed.\n" ); |
147 | REMARK("passed.\n" ); |
148 | }, 42, 64); |
149 | myThread.join(); |
150 | |
151 | #if __TBB_TASK_GROUP_CONTEXT |
152 | // test task_group |
153 | REMARK("Testing task_group... " ); |
154 | int result; |
155 | result = Fib(32); |
156 | ASSERT(result==2178309, "task_group w/lambda failed.\n" ); |
157 | REMARK("passed.\n" ); |
158 | #endif /* __TBB_TASK_GROUP_CONTEXT */ |
159 | |
160 | // Reset array a to index values |
161 | parallel_for(blocked_range<int>(0,N,Grainsize), |
162 | [&] (blocked_range<int>& r) { |
163 | for (int i=r.begin(); i!=r.end(); ++i) a[i] = i; |
164 | }); |
165 | // test parallel_sort |
166 | REMARK("Testing parallel_sort... " ); |
167 | int pivot = 42; |
168 | |
169 | // sort nearest by increasing distance from pivot |
170 | parallel_sort(a, a+N, |
171 | [&](int x, int y) { return(abs(pivot-x) < abs(pivot-y)); }); |
172 | ASSERT(a[0]==42 && a[N-1]==N-1, "parallel_sort w/lambda failed.\n" ); |
173 | REMARK("passed.\n" ); |
174 | |
175 | //test combinable |
176 | REMARK("Testing combinable... " ); |
177 | combinable<std::pair<int,int> > minmax_c([&]() { return std::make_pair(a[0], a[0]); } ); |
178 | |
179 | parallel_for(blocked_range<int>(0,N), |
180 | [&] (const blocked_range<int> &r) { |
181 | std::pair<int,int>& mmr = minmax_c.local(); |
182 | for(int i=r.begin(); i!=r.end(); ++i) { |
183 | if (mmr.first > a[i]) mmr.first = a[i]; |
184 | if (mmr.second < a[i]) mmr.second = a[i]; |
185 | } |
186 | }); |
187 | max_sum = 0; |
188 | minmax_c.combine_each([&max_sum](std::pair<int,int> x) { |
189 | int tsum = x.first + x.second; |
190 | if( tsum>max_sum ) max_sum = tsum; |
191 | }); |
192 | ASSERT( (N-1)<=max_sum && max_sum<=a[0]+N-1, "combinable::combine_each /w lambda failed." ); |
193 | |
194 | std::pair<int,int> minmax_result_c; |
195 | minmax_result_c = |
196 | minmax_c.combine([](std::pair<int,int> x, std::pair<int,int> y) { |
197 | return std::make_pair(x.first<y.first?x.first:y.first, |
198 | x.second>y.second?x.second:y.second); |
199 | }); |
200 | ASSERT(minmax_result_c.first==0 && minmax_result_c.second==999, |
201 | "combinable w/lambda failed.\n" ); |
202 | REMARK("passed.\n" ); |
203 | |
204 | //test enumerable_thread_specific |
205 | REMARK("Testing enumerable_thread_specific... " ); |
206 | enumerable_thread_specific< std::pair<int,int> > minmax_ets([&]() { return std::make_pair(a[0], a[0]); } ); |
207 | |
208 | max_sum = 0; |
209 | parallel_for(blocked_range<int>(0,N), |
210 | [&] (const blocked_range<int> &r) { |
211 | std::pair<int,int>& mmr = minmax_ets.local(); |
212 | for(int i=r.begin(); i!=r.end(); ++i) { |
213 | if (mmr.first > a[i]) mmr.first = a[i]; |
214 | if (mmr.second < a[i]) mmr.second = a[i]; |
215 | } |
216 | }); |
217 | minmax_ets.combine_each([&max_sum](std::pair<int,int> x) { |
218 | int tsum = x.first + x.second; |
219 | if( tsum>max_sum ) max_sum = tsum; |
220 | }); |
221 | ASSERT( (N-1)<=max_sum && max_sum<=a[0]+N-1, "enumerable_thread_specific::combine_each /w lambda failed." ); |
222 | |
223 | std::pair<int,int> minmax_result_ets; |
224 | minmax_result_ets = |
225 | minmax_ets.combine([](std::pair<int,int> x, std::pair<int,int> y) { |
226 | return std::make_pair(x.first<y.first?x.first:y.first, |
227 | x.second>y.second?x.second:y.second); |
228 | }); |
229 | ASSERT(minmax_result_ets.first==0 && minmax_result_ets.second==999, |
230 | "enumerable_thread_specific w/lambda failed.\n" ); |
231 | REMARK("passed.\n" ); |
232 | } |
233 | return Harness::Done; |
234 | } |
235 | #endif /* __TBB_TEST_SKIP_LAMBDA */ |
236 | |