2 Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved.
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
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.
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.
31 #include "compiler_if_host.h"
36 #endif // TARGET_WINNT
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;
45 extern "C" OFFLOAD
OFFLOAD_TARGET_ACQUIRE(
46 TARGET_TYPE target_type
,
49 _Offload_status
* status
,
59 status
->result
= OFFLOAD_UNAVAILABLE
;
60 status
->device_number
= -1;
61 status
->data_sent
= 0;
62 status
->data_received
= 0;
65 // make sure libray is initialized
66 retval
= __offload_init_library();
68 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library
69 OffloadHostTimerData
* timer_data
= OFFLOAD_TIMER_INIT(file
, line
);
71 OFFLOAD_TIMER_START(timer_data
, c_offload_host_total_offload
);
73 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
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();
81 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
83 OFFLOAD_TIMER_START(timer_data
, c_offload_host_target_acquire
);
85 if (target_type
== TARGET_HOST
) {
86 // Host always available
89 else if (target_type
== TARGET_MIC
) {
90 if (target_number
>= -1) {
92 if (target_number
>= 0) {
93 // User provided the device number
94 target_number
= target_number
% mic_engines_total
;
101 // reserve device in ORSL
103 if (!ORSL::try_reserve(target_number
)) {
108 if (!ORSL::reserve(target_number
)) {
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
);
126 if (target_number
< 0 || !retval
) {
127 if (!is_optional
&& status
== 0) {
128 LIBOFFLOAD_ERROR(c_device_is_not_available
);
136 LIBOFFLOAD_ERROR(c_invalid_device_number
);
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
);
151 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_target_acquire
);
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
);
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
,
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");
180 // OFFLOAD_TIMER_INIT must follow call to __offload_init_library
182 OffloadHostTimerData
* timer_data
= OFFLOAD_TIMER_INIT(file
, line
);
184 OFFLOAD_TIMER_START(timer_data
, c_offload_host_total_offload
);
186 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
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();
194 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
196 OFFLOAD_TIMER_START(timer_data
, c_offload_host_target_acquire
);
198 // use default device number if it is not provided
199 if (device_num
!= 0) {
200 target_number
= *device_num
;
203 target_number
= __omp_device_num
;
206 // device number should be a non-negative integer value
207 if (target_number
< 0) {
208 LIBOFFLOAD_ERROR(c_omp_invalid_device_num
);
212 // should we do this for OpenMP?
213 target_number
%= mic_engines_total
;
215 // reserve device in ORSL
216 if (!ORSL::reserve(target_number
)) {
217 LIBOFFLOAD_ERROR(c_device_is_not_available
);
221 // initialize device(s)
222 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
224 if (__offload_init_type
== c_init_on_offload
) {
225 mic_engines
[target_number
].init();
228 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
231 new OffloadDescriptor(target_number
, 0, true, true, timer_data
);
233 OFFLOAD_TIMER_HOST_MIC_NUM(timer_data
, target_number
);
235 Offload_Report_Prolog(timer_data
);
237 OFFLOAD_DEBUG_TRACE_1(2, timer_data
->offload_number
, c_offload_start
,
238 "Starting OpenMP offload, device = %d\n",
241 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_target_acquire
);
246 extern "C" OFFLOAD
OFFLOAD_TARGET_ACQUIRE2(
247 TARGET_TYPE target_type
,
250 _Offload_status
* status
,
261 status
->result
= OFFLOAD_UNAVAILABLE
;
262 status
->device_number
= -1;
263 status
->data_sent
= 0;
264 status
->data_received
= 0;
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
);
272 OFFLOAD_TIMER_START(timer_data
, c_offload_host_total_offload
);
274 OFFLOAD_TIMER_START(timer_data
, c_offload_host_initialize
);
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();
282 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_initialize
);
284 OFFLOAD_TIMER_START(timer_data
, c_offload_host_target_acquire
);
286 if (target_type
== TARGET_HOST
) {
287 // Host always available
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) {
295 // device number is defined by stream
297 target_number
= stream
->get_device();
298 target_number
= target_number
% mic_engines_total
;
301 // reserve device in ORSL
302 if (target_number
!= -1) {
304 if (!ORSL::try_reserve(target_number
)) {
309 if (!ORSL::reserve(target_number
)) {
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
);
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
);
339 LIBOFFLOAD_ERROR(c_invalid_device_number
);
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
);
354 OFFLOAD_TIMER_STOP(timer_data
, c_offload_host_target_acquire
);
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
);
367 static int offload_offload_wrap(
378 const void *stack_addr
,
379 OffloadFlags offload_flags
383 ofld
->set_signal(*signal
);
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
)) {
396 extern "C" int OFFLOAD_OFFLOAD1(
408 return offload_offload_wrap(ofld
, name
, is_empty
,
409 num_vars
, vars
, vars2
,
411 signal
, 0, NULL
, {0});
414 extern "C" int OFFLOAD_OFFLOAD2(
425 const void *stack_addr
428 return offload_offload_wrap(ofld
, name
, is_empty
,
429 num_vars
, vars
, vars2
,
431 signal
, entry_id
, stack_addr
, {0});
434 extern "C" int OFFLOAD_OFFLOAD3(
445 const void *stack_addr
,
446 OffloadFlags offload_flags
,
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
453 ofld
->set_stream(*(reinterpret_cast<_Offload_stream
*>(stream
)));
456 return offload_offload_wrap(ofld
, name
, is_empty
,
457 num_vars
, vars
, vars2
,
459 signal
, entry_id
, stack_addr
, offload_flags
);
462 extern "C" int OFFLOAD_OFFLOAD(
473 const void *stack_addr
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;
481 // remove NULL values from the list of signals to wait for
483 waits_new
= (const void**) alloca(sizeof(void*) * num_waits
);
484 for (int i
= 0; i
< num_waits
; i
++) {
486 waits_new
[num_waits_new
++] = waits
[i
];
491 return OFFLOAD_OFFLOAD1(ofld
, name
, is_empty
,
492 num_vars
, vars
, vars2
,
493 num_waits_new
, waits_new
,
497 extern "C" int OFFLOAD_CALL_COUNT()
499 offload_call_count
++;
500 return offload_call_count
;