Mercurial > hg > CbC > CbC_gcc
comparison liboffloadmic/runtime/compiler_if_host.cpp @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* | |
2 Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved. | |
3 | |
4 Redistribution and use in source and binary forms, with or without | |
5 modification, are permitted provided that the following conditions | |
6 are met: | |
7 | |
8 * Redistributions of source code must retain the above copyright | |
9 notice, this list of conditions and the following disclaimer. | |
10 * Redistributions in binary form must reproduce the above copyright | |
11 notice, this list of conditions and the following disclaimer in the | |
12 documentation and/or other materials provided with the distribution. | |
13 * Neither the name of Intel Corporation nor the names of its | |
14 contributors may be used to endorse or promote products derived | |
15 from this software without specific prior written permission. | |
16 | |
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
18 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
19 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
20 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
21 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
22 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
24 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
25 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
26 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
27 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 */ | |
29 | |
30 | |
31 #include "compiler_if_host.h" | |
32 | |
33 #include <malloc.h> | |
34 #ifndef TARGET_WINNT | |
35 #include <alloca.h> | |
36 #endif // TARGET_WINNT | |
37 | |
38 // Global counter on host. | |
39 // This variable is used if P2OPT_offload_do_data_persistence == 2. | |
40 // The variable used to identify offload constructs contained in one procedure. | |
41 // Increment of OFFLOAD_CALL_COUNT is inserted at entries of HOST routines with | |
42 // offload constructs. | |
43 static int offload_call_count = 0; | |
44 | |
45 extern "C" OFFLOAD OFFLOAD_TARGET_ACQUIRE( | |
46 TARGET_TYPE target_type, | |
47 int target_number, | |
48 int is_optional, | |
49 _Offload_status* status, | |
50 const char* file, | |
51 uint64_t line | |
52 ) | |
53 { | |
54 bool retval; | |
55 OFFLOAD ofld; | |
56 | |
57 // initialize status | |
58 if (status != 0) { | |
59 status->result = OFFLOAD_UNAVAILABLE; | |
60 status->device_number = -1; | |
61 status->data_sent = 0; | |
62 status->data_received = 0; | |
63 } | |
64 | |
65 // make sure libray is initialized | |
66 retval = __offload_init_library(); | |
67 | |
68 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library | |
69 OffloadHostTimerData * timer_data = OFFLOAD_TIMER_INIT(file, line); | |
70 | |
71 OFFLOAD_TIMER_START(timer_data, c_offload_host_total_offload); | |
72 | |
73 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize); | |
74 | |
75 // initialize all devices is init_type is on_offload_all | |
76 if (retval && __offload_init_type == c_init_on_offload_all) { | |
77 for (int i = 0; i < mic_engines_total; i++) { | |
78 mic_engines[i].init(); | |
79 } | |
80 } | |
81 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize); | |
82 | |
83 OFFLOAD_TIMER_START(timer_data, c_offload_host_target_acquire); | |
84 | |
85 if (target_type == TARGET_HOST) { | |
86 // Host always available | |
87 retval = true; | |
88 } | |
89 else if (target_type == TARGET_MIC) { | |
90 if (target_number >= -1) { | |
91 if (retval) { | |
92 if (target_number >= 0) { | |
93 // User provided the device number | |
94 target_number = target_number % mic_engines_total; | |
95 } | |
96 else { | |
97 // use device 0 | |
98 target_number = 0; | |
99 } | |
100 | |
101 // reserve device in ORSL | |
102 if (is_optional) { | |
103 if (!ORSL::try_reserve(target_number)) { | |
104 target_number = -1; | |
105 } | |
106 } | |
107 else { | |
108 if (!ORSL::reserve(target_number)) { | |
109 target_number = -1; | |
110 } | |
111 } | |
112 | |
113 // initialize device | |
114 if (target_number >= 0 && | |
115 __offload_init_type == c_init_on_offload) { | |
116 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize); | |
117 mic_engines[target_number].init(); | |
118 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize); | |
119 } | |
120 } | |
121 else { | |
122 // fallback to CPU | |
123 target_number = -1; | |
124 } | |
125 | |
126 if (target_number < 0 || !retval) { | |
127 if (!is_optional && status == 0) { | |
128 LIBOFFLOAD_ERROR(c_device_is_not_available); | |
129 exit(1); | |
130 } | |
131 | |
132 retval = false; | |
133 } | |
134 } | |
135 else { | |
136 LIBOFFLOAD_ERROR(c_invalid_device_number); | |
137 exit(1); | |
138 } | |
139 } | |
140 | |
141 if (retval) { | |
142 ofld = new OffloadDescriptor(target_number, status, | |
143 !is_optional, false, timer_data); | |
144 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data, target_number); | |
145 Offload_Report_Prolog(timer_data); | |
146 OFFLOAD_DEBUG_TRACE_1(2, timer_data->offload_number, c_offload_start, | |
147 "Starting offload: target_type = %d, " | |
148 "number = %d, is_optional = %d\n", | |
149 target_type, target_number, is_optional); | |
150 | |
151 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire); | |
152 } | |
153 else { | |
154 ofld = NULL; | |
155 | |
156 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire); | |
157 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_total_offload); | |
158 offload_report_free_data(timer_data); | |
159 } | |
160 | |
161 return ofld; | |
162 } | |
163 | |
164 // This routine is called for OpenMP4.5 offload calls | |
165 // OpenMP 4.5 offload is always optional. | |
166 extern "C" OFFLOAD OFFLOAD_TARGET_ACQUIRE1( | |
167 const int* device_num, | |
168 const char* file, | |
169 uint64_t line | |
170 ) | |
171 { | |
172 int target_number; | |
173 | |
174 // make sure libray is initialized and at least one device is available | |
175 if (!__offload_init_library()) { | |
176 OFFLOAD_DEBUG_TRACE(2, "No device available, fall back to host\n"); | |
177 return NULL; | |
178 } | |
179 | |
180 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library | |
181 | |
182 OffloadHostTimerData * timer_data = OFFLOAD_TIMER_INIT(file, line); | |
183 | |
184 OFFLOAD_TIMER_START(timer_data, c_offload_host_total_offload); | |
185 | |
186 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize); | |
187 | |
188 if (__offload_init_type == c_init_on_offload_all) { | |
189 for (int i = 0; i < mic_engines_total; i++) { | |
190 mic_engines[i].init(); | |
191 } | |
192 } | |
193 | |
194 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize); | |
195 | |
196 OFFLOAD_TIMER_START(timer_data, c_offload_host_target_acquire); | |
197 | |
198 // use default device number if it is not provided | |
199 if (device_num != 0) { | |
200 target_number = *device_num; | |
201 } | |
202 else { | |
203 target_number = __omp_device_num; | |
204 } | |
205 | |
206 // device number should be a non-negative integer value | |
207 if (target_number < 0) { | |
208 LIBOFFLOAD_ERROR(c_omp_invalid_device_num); | |
209 exit(1); | |
210 } | |
211 | |
212 // should we do this for OpenMP? | |
213 target_number %= mic_engines_total; | |
214 | |
215 // reserve device in ORSL | |
216 if (!ORSL::reserve(target_number)) { | |
217 LIBOFFLOAD_ERROR(c_device_is_not_available); | |
218 exit(1); | |
219 } | |
220 | |
221 // initialize device(s) | |
222 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize); | |
223 | |
224 if (__offload_init_type == c_init_on_offload) { | |
225 mic_engines[target_number].init(); | |
226 } | |
227 | |
228 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize); | |
229 | |
230 OFFLOAD ofld = | |
231 new OffloadDescriptor(target_number, 0, true, true, timer_data); | |
232 | |
233 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data, target_number); | |
234 | |
235 Offload_Report_Prolog(timer_data); | |
236 | |
237 OFFLOAD_DEBUG_TRACE_1(2, timer_data->offload_number, c_offload_start, | |
238 "Starting OpenMP offload, device = %d\n", | |
239 target_number); | |
240 | |
241 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire); | |
242 | |
243 return ofld; | |
244 } | |
245 | |
246 extern "C" OFFLOAD OFFLOAD_TARGET_ACQUIRE2( | |
247 TARGET_TYPE target_type, | |
248 int target_number, | |
249 int is_optional, | |
250 _Offload_status* status, | |
251 const char* file, | |
252 uint64_t line, | |
253 const void** stream | |
254 ) | |
255 { | |
256 bool retval; | |
257 OFFLOAD ofld; | |
258 | |
259 // initialize status | |
260 if (status != 0) { | |
261 status->result = OFFLOAD_UNAVAILABLE; | |
262 status->device_number = -1; | |
263 status->data_sent = 0; | |
264 status->data_received = 0; | |
265 } | |
266 | |
267 // make sure libray is initialized | |
268 retval = __offload_init_library(); | |
269 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library | |
270 OffloadHostTimerData * timer_data = OFFLOAD_TIMER_INIT(file, line); | |
271 | |
272 OFFLOAD_TIMER_START(timer_data, c_offload_host_total_offload); | |
273 | |
274 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize); | |
275 | |
276 // initalize all devices if init_type is on_offload_all | |
277 if (retval && __offload_init_type == c_init_on_offload_all) { | |
278 for (int i = 0; i < mic_engines_total; i++) { | |
279 mic_engines[i].init(); | |
280 } | |
281 } | |
282 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize); | |
283 | |
284 OFFLOAD_TIMER_START(timer_data, c_offload_host_target_acquire); | |
285 | |
286 if (target_type == TARGET_HOST) { | |
287 // Host always available | |
288 retval = true; | |
289 } | |
290 else if (target_type == TARGET_MIC) { | |
291 _Offload_stream handle = *(reinterpret_cast<_Offload_stream*>(stream)); | |
292 Stream * stream = handle ? Stream::find_stream(handle, false) : NULL; | |
293 if (target_number >= -1) { | |
294 if (retval) { | |
295 // device number is defined by stream | |
296 if (stream) { | |
297 target_number = stream->get_device(); | |
298 target_number = target_number % mic_engines_total; | |
299 } | |
300 | |
301 // reserve device in ORSL | |
302 if (target_number != -1) { | |
303 if (is_optional) { | |
304 if (!ORSL::try_reserve(target_number)) { | |
305 target_number = -1; | |
306 } | |
307 } | |
308 else { | |
309 if (!ORSL::reserve(target_number)) { | |
310 target_number = -1; | |
311 } | |
312 } | |
313 } | |
314 | |
315 // initialize device | |
316 if (target_number >= 0 && | |
317 __offload_init_type == c_init_on_offload) { | |
318 OFFLOAD_TIMER_START(timer_data, c_offload_host_initialize); | |
319 mic_engines[target_number].init(); | |
320 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_initialize); | |
321 } | |
322 } | |
323 else { | |
324 // fallback to CPU | |
325 target_number = -1; | |
326 } | |
327 if (!(target_number == -1 && handle == 0)) { | |
328 if (target_number < 0 || !retval) { | |
329 if (!is_optional && status == 0) { | |
330 LIBOFFLOAD_ERROR(c_device_is_not_available); | |
331 exit(1); | |
332 } | |
333 | |
334 retval = false; | |
335 } | |
336 } | |
337 } | |
338 else { | |
339 LIBOFFLOAD_ERROR(c_invalid_device_number); | |
340 exit(1); | |
341 } | |
342 } | |
343 | |
344 if (retval) { | |
345 ofld = new OffloadDescriptor(target_number, status, | |
346 !is_optional, false, timer_data); | |
347 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data, target_number); | |
348 Offload_Report_Prolog(timer_data); | |
349 OFFLOAD_DEBUG_TRACE_1(2, timer_data->offload_number, c_offload_start, | |
350 "Starting offload: target_type = %d, " | |
351 "number = %d, is_optional = %d\n", | |
352 target_type, target_number, is_optional); | |
353 | |
354 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire); | |
355 } | |
356 else { | |
357 ofld = NULL; | |
358 | |
359 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_target_acquire); | |
360 OFFLOAD_TIMER_STOP(timer_data, c_offload_host_total_offload); | |
361 offload_report_free_data(timer_data); | |
362 } | |
363 | |
364 return ofld; | |
365 } | |
366 | |
367 static int offload_offload_wrap( | |
368 OFFLOAD ofld, | |
369 const char *name, | |
370 int is_empty, | |
371 int num_vars, | |
372 VarDesc *vars, | |
373 VarDesc2 *vars2, | |
374 int num_waits, | |
375 const void **waits, | |
376 const void **signal, | |
377 int entry_id, | |
378 const void *stack_addr, | |
379 OffloadFlags offload_flags | |
380 ) | |
381 { | |
382 if (signal) { | |
383 ofld->set_signal(*signal); | |
384 } | |
385 | |
386 bool ret = ofld->offload(name, is_empty, vars, vars2, num_vars, | |
387 waits, num_waits, signal, entry_id, | |
388 stack_addr, offload_flags); | |
389 if (!ret || (signal == 0 && ofld->get_stream() == 0 && | |
390 !offload_flags.bits.omp_async)) { | |
391 delete ofld; | |
392 } | |
393 return ret; | |
394 } | |
395 | |
396 extern "C" int OFFLOAD_OFFLOAD1( | |
397 OFFLOAD ofld, | |
398 const char *name, | |
399 int is_empty, | |
400 int num_vars, | |
401 VarDesc *vars, | |
402 VarDesc2 *vars2, | |
403 int num_waits, | |
404 const void **waits, | |
405 const void **signal | |
406 ) | |
407 { | |
408 return offload_offload_wrap(ofld, name, is_empty, | |
409 num_vars, vars, vars2, | |
410 num_waits, waits, | |
411 signal, 0, NULL, {0}); | |
412 } | |
413 | |
414 extern "C" int OFFLOAD_OFFLOAD2( | |
415 OFFLOAD ofld, | |
416 const char *name, | |
417 int is_empty, | |
418 int num_vars, | |
419 VarDesc *vars, | |
420 VarDesc2 *vars2, | |
421 int num_waits, | |
422 const void** waits, | |
423 const void** signal, | |
424 int entry_id, | |
425 const void *stack_addr | |
426 ) | |
427 { | |
428 return offload_offload_wrap(ofld, name, is_empty, | |
429 num_vars, vars, vars2, | |
430 num_waits, waits, | |
431 signal, entry_id, stack_addr, {0}); | |
432 } | |
433 | |
434 extern "C" int OFFLOAD_OFFLOAD3( | |
435 OFFLOAD ofld, | |
436 const char *name, | |
437 int is_empty, | |
438 int num_vars, | |
439 VarDesc *vars, | |
440 VarDesc2 *vars2, | |
441 int num_waits, | |
442 const void** waits, | |
443 const void** signal, | |
444 int entry_id, | |
445 const void *stack_addr, | |
446 OffloadFlags offload_flags, | |
447 const void** stream | |
448 ) | |
449 { | |
450 // 1. if the source is compiled with -traceback then stream is 0 | |
451 // 2. if offload has a stream clause then stream is address of stream value | |
452 if (stream) { | |
453 ofld->set_stream(*(reinterpret_cast<_Offload_stream *>(stream))); | |
454 } | |
455 | |
456 return offload_offload_wrap(ofld, name, is_empty, | |
457 num_vars, vars, vars2, | |
458 num_waits, waits, | |
459 signal, entry_id, stack_addr, offload_flags); | |
460 } | |
461 | |
462 extern "C" int OFFLOAD_OFFLOAD( | |
463 OFFLOAD ofld, | |
464 const char *name, | |
465 int is_empty, | |
466 int num_vars, | |
467 VarDesc *vars, | |
468 VarDesc2 *vars2, | |
469 int num_waits, | |
470 const void **waits, | |
471 const void *signal, | |
472 int entry_id, | |
473 const void *stack_addr | |
474 ) | |
475 { | |
476 // signal is passed by reference now | |
477 const void **signal_new = (signal != 0) ? &signal : 0; | |
478 const void **waits_new = 0; | |
479 int num_waits_new = 0; | |
480 | |
481 // remove NULL values from the list of signals to wait for | |
482 if (num_waits > 0) { | |
483 waits_new = (const void**) alloca(sizeof(void*) * num_waits); | |
484 for (int i = 0; i < num_waits; i++) { | |
485 if (waits[i] != 0) { | |
486 waits_new[num_waits_new++] = waits[i]; | |
487 } | |
488 } | |
489 } | |
490 | |
491 return OFFLOAD_OFFLOAD1(ofld, name, is_empty, | |
492 num_vars, vars, vars2, | |
493 num_waits_new, waits_new, | |
494 signal_new); | |
495 } | |
496 | |
497 extern "C" int OFFLOAD_CALL_COUNT() | |
498 { | |
499 offload_call_count++; | |
500 return offload_call_count; | |
501 } |