542 lines
17 KiB
C++
542 lines
17 KiB
C++
/*
|
|
Copyright (c) 2014-2016 Intel Corporation. All Rights Reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
* Neither the name of Intel Corporation nor the names of its
|
|
contributors may be used to endorse or promote products derived
|
|
from this software without specific prior written permission.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
|
|
/*! \file
|
|
\brief The parts of the runtime library used only on the host
|
|
*/
|
|
|
|
#ifndef OFFLOAD_HOST_H_INCLUDED
|
|
#define OFFLOAD_HOST_H_INCLUDED
|
|
|
|
#ifndef TARGET_WINNT
|
|
#include <unistd.h>
|
|
#endif // TARGET_WINNT
|
|
#include "offload_common.h"
|
|
#include "offload_util.h"
|
|
#include "offload_engine.h"
|
|
#include "offload_env.h"
|
|
#include "offload_orsl.h"
|
|
#include "coi/coi_client.h"
|
|
|
|
// MIC engines.
|
|
DLL_LOCAL extern Engine* mic_engines;
|
|
DLL_LOCAL extern uint32_t mic_engines_total;
|
|
|
|
// DMA channel count used by COI and set via
|
|
// OFFLOAD_DMA_CHANNEL_COUNT environment variable
|
|
DLL_LOCAL extern uint32_t mic_dma_channel_count;
|
|
|
|
//! The target image is packed as follows.
|
|
/*! 1. 8 bytes containing the size of the target binary */
|
|
/*! 2. a null-terminated string which is the binary name */
|
|
/*! 3. <size> number of bytes that are the contents of the image */
|
|
/*! The address of symbol __offload_target_image
|
|
is the address of this structure. */
|
|
struct Image {
|
|
int64_t size; //!< Size in bytes of the target binary name and contents
|
|
char data[]; //!< The name and contents of the target image
|
|
};
|
|
|
|
// The offload descriptor.
|
|
class OffloadDescriptor
|
|
{
|
|
public:
|
|
enum OmpAsyncLastEventType {
|
|
c_last_not, // not last event
|
|
c_last_write, // the last event that is write
|
|
c_last_read, // the last event that is read
|
|
c_last_runfunc // the last event that is runfunction
|
|
};
|
|
|
|
OffloadDescriptor(
|
|
int index,
|
|
_Offload_status *status,
|
|
bool is_mandatory,
|
|
bool is_openmp,
|
|
OffloadHostTimerData * timer_data
|
|
) :
|
|
m_device(mic_engines[index == -1 ? 0 : index % mic_engines_total]),
|
|
m_is_mandatory(is_mandatory),
|
|
m_is_openmp(is_openmp),
|
|
m_inout_buf(0),
|
|
m_func_desc(0),
|
|
m_func_desc_size(0),
|
|
m_num_in_dependencies(0),
|
|
m_p_in_dependencies(0),
|
|
m_in_deps(0),
|
|
m_in_deps_total(0),
|
|
m_in_deps_allocated(0),
|
|
m_out_deps(0),
|
|
m_out_deps_total(0),
|
|
m_out_deps_allocated(0),
|
|
m_vars(0),
|
|
m_vars_extra(0),
|
|
m_status(status),
|
|
m_timer_data(timer_data),
|
|
m_out_with_preallocated(false),
|
|
m_preallocated_alloc(false),
|
|
m_traceback_called(false),
|
|
m_stream(-1),
|
|
m_signal(0),
|
|
m_has_signal(0),
|
|
m_omp_async_last_event_type(c_last_not)
|
|
{
|
|
m_wait_all_devices = index == -1;
|
|
}
|
|
|
|
~OffloadDescriptor()
|
|
{
|
|
if (m_in_deps != 0) {
|
|
free(m_in_deps);
|
|
}
|
|
if (m_out_deps != 0) {
|
|
free(m_out_deps);
|
|
}
|
|
if (m_func_desc != 0) {
|
|
free(m_func_desc);
|
|
}
|
|
if (m_vars != 0) {
|
|
free(m_vars);
|
|
free(m_vars_extra);
|
|
}
|
|
}
|
|
|
|
bool offload(const char *name, bool is_empty,
|
|
VarDesc *vars, VarDesc2 *vars2, int vars_total,
|
|
const void **waits, int num_waits, const void **signal,
|
|
int entry_id, const void *stack_addr,
|
|
OffloadFlags offload_flags);
|
|
|
|
bool offload_finish(bool is_traceback);
|
|
|
|
bool is_signaled();
|
|
|
|
OffloadHostTimerData* get_timer_data() const {
|
|
return m_timer_data;
|
|
}
|
|
|
|
void set_stream(_Offload_stream stream) {
|
|
m_stream = stream;
|
|
}
|
|
|
|
_Offload_stream get_stream() {
|
|
return(m_stream);
|
|
}
|
|
|
|
Engine& get_device() {
|
|
return m_device;
|
|
}
|
|
|
|
void* get_signal() {
|
|
return(m_signal);
|
|
}
|
|
|
|
void set_signal(const void* signal) {
|
|
m_has_signal = 1;
|
|
m_signal = const_cast<void*>(signal);
|
|
}
|
|
|
|
void cleanup();
|
|
|
|
uint32_t m_event_count;
|
|
bool m_has_signal;
|
|
|
|
private:
|
|
bool offload_wrap(const char *name, bool is_empty,
|
|
VarDesc *vars, VarDesc2 *vars2, int vars_total,
|
|
const void **waits, int num_waits, const void **signal,
|
|
int entry_id, const void *stack_addr,
|
|
OffloadFlags offload_flags);
|
|
bool wait_dependencies(const void **waits, int num_waits,
|
|
_Offload_stream stream);
|
|
bool setup_descriptors(VarDesc *vars, VarDesc2 *vars2, int vars_total,
|
|
int entry_id, const void *stack_addr);
|
|
bool setup_misc_data(const char *name);
|
|
bool send_pointer_data(bool is_async, void* info);
|
|
bool send_noncontiguous_pointer_data(
|
|
int i,
|
|
PtrData* src_buf,
|
|
PtrData* dst_buf,
|
|
COIEVENT *event,
|
|
uint64_t &sent_data,
|
|
uint32_t in_deps_amount,
|
|
COIEVENT *in_deps
|
|
);
|
|
bool receive_noncontiguous_pointer_data(
|
|
int i,
|
|
COIBUFFER dst_buf,
|
|
COIEVENT *event,
|
|
uint64_t &received_data,
|
|
uint32_t in_deps_amount,
|
|
COIEVENT *in_deps
|
|
);
|
|
|
|
bool gather_copyin_data();
|
|
|
|
bool compute(void *);
|
|
|
|
bool receive_pointer_data(bool is_async, bool first_run, void * info);
|
|
bool scatter_copyout_data();
|
|
|
|
bool find_ptr_data(PtrData* &ptr_data, void *base, int64_t disp,
|
|
int64_t length, bool is_targptr,
|
|
bool error_does_not_exist = true);
|
|
|
|
void find_device_ptr( int64_t* &device_ptr,
|
|
void *host_ptr);
|
|
|
|
bool alloc_ptr_data(PtrData* &ptr_data, void *base, int64_t disp,
|
|
int64_t length, int64_t alloc_disp, int align,
|
|
bool is_targptr, bool is_prealloc, bool pin);
|
|
bool create_preallocated_buffer(PtrData* ptr_data, void *base);
|
|
bool init_static_ptr_data(PtrData *ptr_data);
|
|
bool init_mic_address(PtrData *ptr_data);
|
|
bool offload_stack_memory_manager(
|
|
const void * stack_begin,
|
|
int routine_id,
|
|
int buf_size,
|
|
int align,
|
|
bool thread_specific_function_locals,
|
|
bool *is_new);
|
|
char *get_this_threads_cpu_stack_addr(
|
|
const void * stack_begin,
|
|
int routine_id,
|
|
bool thread_specific_function_locals);
|
|
PtrData *get_this_threads_mic_stack_addr(
|
|
const void * stack_begin,
|
|
int routine_id,
|
|
bool thread_specific_function_locals);
|
|
bool nullify_target_stack(COIBUFFER targ_buf, uint64_t size);
|
|
|
|
bool gen_var_descs_for_pointer_array(int i);
|
|
|
|
void get_stream_in_dependencies(uint32_t &in_deps_amount,
|
|
COIEVENT* &in_deps);
|
|
|
|
void report_coi_error(error_types msg, COIRESULT res);
|
|
_Offload_result translate_coi_error(COIRESULT res) const;
|
|
|
|
void setup_omp_async_info();
|
|
|
|
void setup_use_device_ptr(int i);
|
|
|
|
void register_event_call_back(void (*)(
|
|
COIEVENT,
|
|
const COIRESULT,
|
|
const void*),
|
|
const COIEVENT *event,
|
|
const void *info);
|
|
|
|
void register_omp_event_call_back(const COIEVENT *event, const void *info);
|
|
|
|
private:
|
|
typedef std::list<COIBUFFER> BufferList;
|
|
|
|
// extra data associated with each variable descriptor
|
|
struct VarExtra {
|
|
PtrData* src_data;
|
|
PtrData* dst_data;
|
|
AutoData* auto_data;
|
|
int64_t cpu_disp;
|
|
int64_t cpu_offset;
|
|
void *alloc;
|
|
union {
|
|
CeanReadRanges *read_rng_src;
|
|
NonContigDesc *noncont_desc;
|
|
};
|
|
CeanReadRanges *read_rng_dst;
|
|
int64_t ptr_arr_offset;
|
|
bool is_arr_ptr_el;
|
|
OmpAsyncLastEventType omp_last_event_type;
|
|
int64_t pointer_offset;
|
|
uint16_t type_src;
|
|
uint16_t type_dst;
|
|
};
|
|
|
|
template<typename T> class ReadArrElements {
|
|
public:
|
|
ReadArrElements():
|
|
ranges(NULL),
|
|
el_size(sizeof(T)),
|
|
offset(0),
|
|
count(0),
|
|
is_empty(true),
|
|
base(NULL)
|
|
{}
|
|
|
|
bool read_next(bool flag)
|
|
{
|
|
if (flag != 0) {
|
|
if (is_empty) {
|
|
if (ranges) {
|
|
if (!get_next_range(ranges, &offset)) {
|
|
// ranges are over
|
|
return false;
|
|
}
|
|
}
|
|
// all contiguous elements are over
|
|
else if (count != 0) {
|
|
return false;
|
|
}
|
|
|
|
length_cur = size;
|
|
}
|
|
else {
|
|
offset += el_size;
|
|
}
|
|
val = (T)get_el_value(base, offset, el_size);
|
|
length_cur -= el_size;
|
|
count++;
|
|
is_empty = length_cur == 0;
|
|
}
|
|
return true;
|
|
}
|
|
public:
|
|
CeanReadRanges * ranges;
|
|
T val;
|
|
int el_size;
|
|
int64_t size,
|
|
offset,
|
|
length_cur;
|
|
bool is_empty;
|
|
int count;
|
|
char *base;
|
|
};
|
|
|
|
// ptr_data for persistent auto objects
|
|
PtrData* m_stack_ptr_data;
|
|
PtrDataList m_destroy_stack;
|
|
|
|
// Engine
|
|
Engine& m_device;
|
|
|
|
// true for offload_wait target(mic) stream(0)
|
|
bool m_wait_all_devices;
|
|
|
|
// if true offload is mandatory
|
|
bool m_is_mandatory;
|
|
|
|
// if true offload has openmp origin
|
|
const bool m_is_openmp;
|
|
|
|
// The Marshaller for the inputs of the offloaded region.
|
|
Marshaller m_in;
|
|
|
|
// The Marshaller for the outputs of the offloaded region.
|
|
Marshaller m_out;
|
|
|
|
// List of buffers that are passed to dispatch call
|
|
BufferList m_compute_buffers;
|
|
|
|
// List of buffers that need to be destroyed at the end of offload
|
|
BufferList m_destroy_buffers;
|
|
|
|
// Variable descriptors
|
|
VarDesc* m_vars;
|
|
VarExtra* m_vars_extra;
|
|
int m_vars_total;
|
|
|
|
// Pointer to a user-specified status variable
|
|
_Offload_status *m_status;
|
|
|
|
// Function descriptor
|
|
FunctionDescriptor* m_func_desc;
|
|
uint32_t m_func_desc_size;
|
|
|
|
// Buffer for transferring copyin/copyout data
|
|
COIBUFFER m_inout_buf;
|
|
|
|
|
|
// Dependencies
|
|
COIEVENT *m_in_deps;
|
|
uint32_t m_in_deps_total;
|
|
uint32_t m_in_deps_allocated;
|
|
COIEVENT *m_out_deps;
|
|
uint32_t m_out_deps_total;
|
|
uint32_t m_out_deps_allocated;
|
|
|
|
// 2 variables defines input dependencies for current COI API.
|
|
// The calls to routines as BufferWrite/PipelineRunFunction/BufferRead
|
|
// is supposed to have input dependencies.
|
|
// 2 variables below defines the number and vector of dependencies
|
|
// in every current moment of offload.
|
|
// So any phase of offload can use its values as input dependencies
|
|
// for the COI API that the phase calls.
|
|
// It means that all phases (of Write, RunFunction,Read) must keep
|
|
// the variables correct to be used by following phase.
|
|
// If some consequent offloads are connected (i.e. by the same stream)
|
|
// the final 2 variables of the offload is used as initial inputs
|
|
// for the next offload.
|
|
uint32_t m_num_in_dependencies;
|
|
COIEVENT *m_p_in_dependencies;
|
|
|
|
// Stream
|
|
_Offload_stream m_stream;
|
|
|
|
// Signal
|
|
void* m_signal;
|
|
|
|
// Timer data
|
|
OffloadHostTimerData *m_timer_data;
|
|
|
|
// copyin/copyout data length
|
|
uint64_t m_in_datalen;
|
|
uint64_t m_out_datalen;
|
|
|
|
// a boolean value calculated in setup_descriptors. If true we need to do
|
|
// a run function on the target. Otherwise it may be optimized away.
|
|
bool m_need_runfunction;
|
|
|
|
// initialized value of m_need_runfunction;
|
|
// is used to recognize offload_transfer
|
|
bool m_initial_need_runfunction;
|
|
|
|
// a Boolean value set to true when OUT clauses with preallocated targetptr
|
|
// is encountered to indicate that call receive_pointer_data needs to be
|
|
// invoked again after call to scatter_copyout_data.
|
|
bool m_out_with_preallocated;
|
|
|
|
// a Boolean value set to true if an alloc_if(1) is used with preallocated
|
|
// targetptr to indicate the need to scatter_copyout_data even for
|
|
// async offload
|
|
bool m_preallocated_alloc;
|
|
|
|
// a Boolean value set to true if traceback routine is called
|
|
bool m_traceback_called;
|
|
|
|
OmpAsyncLastEventType m_omp_async_last_event_type;
|
|
};
|
|
|
|
// Initialization types for MIC
|
|
enum OffloadInitType {
|
|
c_init_on_start, // all devices before entering main
|
|
c_init_on_offload, // single device before starting the first offload
|
|
c_init_on_offload_all // all devices before starting the first offload
|
|
};
|
|
|
|
// Determines if MIC code is an executable or a shared library
|
|
extern "C" bool __offload_target_image_is_executable(const void *target_image);
|
|
|
|
// Initializes library and registers specified offload image.
|
|
extern "C" bool __offload_register_image(const void* image);
|
|
extern "C" void __offload_unregister_image(const void* image);
|
|
|
|
// Registers asynchronous task completion callback
|
|
extern "C" void __offload_register_task_callback(void (*cb)(void *));
|
|
|
|
// Initializes offload runtime library.
|
|
DLL_LOCAL extern int __offload_init_library(void);
|
|
|
|
// thread data for associating pipelines with threads
|
|
DLL_LOCAL extern pthread_key_t mic_thread_key;
|
|
|
|
// location of offload_main executable
|
|
// To be used if the main application has no offload and is not built
|
|
// with -offload but dynamic library linked in has offload pragma
|
|
DLL_LOCAL extern char* mic_device_main;
|
|
|
|
// Environment variables for devices
|
|
DLL_LOCAL extern MicEnvVar mic_env_vars;
|
|
|
|
// CPU frequency
|
|
DLL_LOCAL extern uint64_t cpu_frequency;
|
|
|
|
// LD_LIBRARY_PATH for KNC libraries
|
|
DLL_LOCAL extern char* knc_library_path;
|
|
|
|
// LD_LIBRARY_PATH for KNL libraries
|
|
DLL_LOCAL extern char* knl_library_path;
|
|
|
|
// stack size for target
|
|
DLL_LOCAL extern uint32_t mic_stack_size;
|
|
|
|
// Preallocated memory size for buffers on MIC
|
|
DLL_LOCAL extern uint64_t mic_buffer_size;
|
|
|
|
// Preallocated 4K page memory size for buffers on MIC
|
|
DLL_LOCAL extern uint64_t mic_4k_buffer_size;
|
|
|
|
// Preallocated 2M page memory size for buffers on MIC
|
|
DLL_LOCAL extern uint64_t mic_2m_buffer_size;
|
|
|
|
// Setting controlling inout proxy
|
|
DLL_LOCAL extern bool mic_proxy_io;
|
|
DLL_LOCAL extern char* mic_proxy_fs_root;
|
|
|
|
// Threshold for creating buffers with large pages
|
|
DLL_LOCAL extern uint64_t __offload_use_2mb_buffers;
|
|
|
|
// offload initialization type
|
|
DLL_LOCAL extern OffloadInitType __offload_init_type;
|
|
|
|
// Device number to offload to when device is not explicitly specified.
|
|
DLL_LOCAL extern int __omp_device_num;
|
|
|
|
// target executable
|
|
DLL_LOCAL extern TargetImage* __target_exe;
|
|
|
|
// is true if last loaded image is dll
|
|
DLL_LOCAL extern bool __current_image_is_dll;
|
|
// is true if myo library is loaded when dll is loaded
|
|
DLL_LOCAL extern bool __myo_init_in_so;
|
|
|
|
// IDB support
|
|
|
|
// Called by the offload runtime after initialization of offload infrastructure
|
|
// has been completed.
|
|
extern "C" void __dbg_target_so_loaded();
|
|
|
|
// Called by the offload runtime when the offload infrastructure is about to be
|
|
// shut down, currently at application exit.
|
|
extern "C" void __dbg_target_so_unloaded();
|
|
|
|
// Null-terminated string containing path to the process image of the hosting
|
|
// application (offload_main)
|
|
#define MAX_TARGET_NAME 512
|
|
extern "C" char __dbg_target_exe_name[MAX_TARGET_NAME];
|
|
|
|
// Integer specifying the process id
|
|
extern "C" pid_t __dbg_target_so_pid;
|
|
|
|
// Integer specifying the 0-based device number
|
|
extern "C" int __dbg_target_id;
|
|
|
|
// Set to non-zero by the host-side debugger to enable offload debugging
|
|
// support
|
|
extern "C" int __dbg_is_attached;
|
|
|
|
// Major version of the debugger support API
|
|
extern "C" const int __dbg_api_major_version;
|
|
|
|
// Minor version of the debugger support API
|
|
extern "C" const int __dbg_api_minor_version;
|
|
|
|
#endif // OFFLOAD_HOST_H_INCLUDED
|