Files
DKS/src/DKSBase.cpp
2017-03-15 10:01:28 +01:00

455 lines
9.4 KiB
C++

#include "DKSBase.h"
#define API_OPENCL "OpenCL"
#define API_CUDA "Cuda"
#define API_OPENMP "OpenMP"
#define DEVICE_GPU "-gpu"
#define DEVICE_CPU "-cpu"
#define DEVICE_MIC "-mic"
//=====================================//
//==========Private functions==========//
//=====================================//
bool DKSBase::apiOpenCL() {
if (!m_api_set)
return false;
if (strcmp(m_api_name, API_OPENCL) != 0)
return false;
return true;
}
bool DKSBase::apiCuda() {
if (!m_api_set)
return false;
if (strcmp(m_api_name, API_CUDA) != 0)
return false;
return true;
}
bool DKSBase::apiOpenMP() {
if (!m_api_set)
return false;
if (strcmp(m_api_name, API_OPENMP) != 0)
return false;
return true;
}
bool DKSBase::deviceGPU() {
if (!m_device_set)
return false;
if (strcmp(m_device_name, DEVICE_GPU) != 0)
return false;
return true;
}
bool DKSBase::deviceCPU() {
if (!m_device_set)
return false;
if (strcmp(m_device_name, DEVICE_CPU) != 0)
return false;
return true;
}
bool DKSBase::deviceMIC() {
if (!m_device_set)
return false;
if (strcmp(m_device_name, DEVICE_MIC) != 0)
return false;
return true;
}
int DKSBase::loadOpenCLKernel(const char *kernel_name) {
//load kernel
char * kernel_file = new char[500];
kernel_file[0] = '\0';
strcat(kernel_file, OPENCL_KERNELS);
strcat(kernel_file, kernel_name);
int ierr = OPENCL_SAFECALL( oclbase->ocl_loadKernel(kernel_file) );
delete[] kernel_file;
return ierr;
}
//=====================================//
//==========Public functions===========//
//=====================================//
DKSBase::DKSBase() {
m_device_name = NULL;
m_api_name = NULL;
m_function_name = NULL;
m_device_set = false;
m_api_set = false;
m_function_set = false;
m_auto_tuning = false;
m_use_config = false;
#ifdef DKS_CUDA
cbase = new CudaBase();
#endif
#ifdef DKS_OPENCL
oclbase = new OpenCLBase();
#endif
#ifdef DKS_MIC
micbase = new MICBase();
#endif
}
DKSBase::DKSBase(const char* api_name, const char* device_name) {
setAPI(api_name, strlen(api_name));
setDevice(device_name, strlen(device_name));
m_function_name = NULL;
m_function_set = false;
m_auto_tuning = false;
m_use_config = false;
#ifdef DKS_CUDA
cbase = new CudaBase();
#endif
#ifdef DKS_OPENCL
oclbase = new OpenCLBase();
#endif
#ifdef DKS_MIC
micbase = new MICBase();
#endif
}
DKSBase::~DKSBase() {
if (m_device_name != NULL)
delete[] m_device_name;
if (m_api_name != NULL)
delete[] m_api_name;
if (m_function_name != NULL)
delete[] m_function_name;
#ifdef DKS_CUDA
delete cbase;
#endif
#ifdef DKS_OPENCL
delete oclbase;
#endif
#ifdef DKS_MIC
delete micbase;
#endif
}
/*
Name: setDevice
Info: sets specific device to use. length specifies device_name string length (deprecated)
Return: success or error code
*/
int DKSBase::setDevice(const char* device_name, int length) {
if (m_device_set)
delete[] m_device_name;
int l = strlen(device_name);
m_device_name = new char[l+1];
for (int i = 0; i < l; i++)
m_device_name[i] = device_name[i];
m_device_name[l] = '\0';
m_device_set = true;
return DKS_SUCCESS;
}
/*
Name: setAPI
Info: sets specific api (OpenCL, CUDA, OpenACC, OpenMP) to use
Return: success or error code
*/
int DKSBase::setAPI(const char* api_name, int length) {
if (m_api_set)
delete[] m_api_name;
int l = strlen(api_name);
m_api_name = new char[l+1];
for (int i = 0; i < l; i++)
m_api_name[i] = api_name[i];
m_api_name[l] = '\0';
m_api_set = true;
return DKS_SUCCESS;
}
/*
Name: getDevices
Info: get all available devices
Return: success or error code
*/
int DKSBase::getDevices() {
int ierr1 = OPENCL_SAFECALL( oclbase->ocl_getAllDevices() );
int ierr2 = CUDA_SAFECALL( cbase->cuda_getDevices() );
int ierr3 = MIC_SAFECALL( micbase->mic_getDevices() );
if (ierr1 + ierr2 + ierr3 != DKS_SUCCESS)
return DKS_ERROR;
return DKS_SUCCESS;
}
int DKSBase::getDeviceCount(int &ndev) {
ndev = 0;
if (apiOpenCL())
return OPENCL_SAFECALL( oclbase->ocl_getDeviceCount(ndev) );
else if (apiCuda())
return CUDA_SAFECALL( cbase->cuda_getDeviceCount(ndev) );
else if (apiOpenMP())
return DKS_ERROR;
else
return DKS_ERROR;
}
int DKSBase::getDeviceName(std::string &device_name) {
if (apiOpenCL())
return OPENCL_SAFECALL( oclbase->ocl_getDeviceName(device_name) );
else if (apiCuda())
return CUDA_SAFECALL( cbase->cuda_getDeviceName(device_name) );
else if (apiOpenMP())
return DKS_ERROR;
else
return DKS_ERROR;
}
int DKSBase::setDefaultDevice(int device) {
std::cout << "Set device " << device << std::endl;
if (apiOpenCL())
return OPENCL_SAFECALL( oclbase->ocl_setDevice(device) );
else if (apiCuda())
return CUDA_SAFECALL( cbase->cuda_setDevice(device) );
else if (apiOpenMP())
return DKS_ERROR;
else
return DKS_ERROR;
}
int DKSBase::getDeviceList(std::vector<int> &devices) {
if (apiOpenCL())
return OPENCL_SAFECALL( oclbase->ocl_getUniqueDevices(devices) );
else if (apiCuda())
return CUDA_SAFECALL( cbase->cuda_getUniqueDevices(devices) );
else if (apiOpenMP())
return DKS_ERROR;
else
return DKS_ERROR;
}
int DKSBase::setupDevice() {
int ierr = DKS_ERROR;
//if api is not set default is OpenCL
if (!m_api_set) {
setDevice("-gpu", 4);
setAPI(API_OPENCL, 6);
ierr = OPENCL_SAFECALL( oclbase->ocl_setUp("-gpu") );
} else {
if (apiOpenCL()) {
if (!m_device_set) {
setDevice("-gpu", 4);
setAPI(API_OPENCL, 6);
ierr = OPENCL_SAFECALL( oclbase->ocl_setUp("-gpu") );
} else {
setAPI(API_OPENCL, 6);
ierr = OPENCL_SAFECALL( oclbase->ocl_setUp(m_device_name) );
}
} else if (apiCuda()) {
setDevice("-gpu", 4);
setAPI(API_CUDA, 4);
ierr = CUDA_SAFECALL(DKS_SUCCESS);
} else if (apiOpenMP()) {
setDevice("-mic", 4);
setAPI(API_OPENMP, 6);
ierr = MIC_SAFECALL(DKS_SUCCESS);
}
}
return ierr;
}
/*
init device
*/
int DKSBase::initDevice() {
return setupDevice();
}
/*
set up cuda, opencl and mic to allow async data transfer and kernel execution.
name stream 'stolen' from cuda. opencl context ~ cuda stream.
TODO: implementations for OpenCL and MIC still needed
*/
int DKSBase::createStream(int &streamId) {
if (apiCuda())
return CUDA_SAFECALL( cbase->cuda_createStream(streamId) );
else if (apiOpenMP())
return MIC_SAFECALL( micbase->mic_createStream(streamId) );
DEBUG_MSG("Streams not enbled for this platforms jet");
return DKS_ERROR;
}
/* send device pointer to other processes */
#ifdef DKS_MPI
int DKSBase::sendPointer(void *mem_ptr, int dest, MPI_Comm comm) {
if ( apiCuda() ) {
#ifdef DKS_CUDA
cudaError cerror;
cudaIpcMemHandle_t shandle;
cerror = cudaIpcGetMemHandle(&shandle, mem_ptr);
MPI_Send(&shandle, sizeof(cudaIpcMemHandle_t), MPI_BYTE, dest, 100, comm);
if (cerror != cudaSuccess) {
DEBUG_MSG("Error geting mem handle");
return DKS_ERROR;
}
return DKS_SUCCESS;
#endif
}
else if (apiOpenMP()) {
#ifdef DKS_MIC
//BENI:
DEBUG_MSG("No SendPointer for MIC is implemented");
return DKS_ERROR;
#endif
}
else {
DEBUG_MSG("Send device pointer not implemented on selected platform");
return DKS_ERROR;
}
return DKS_ERROR;
}
#endif
/* receive device pointer */
#ifdef DKS_MPI
void * DKSBase::receivePointer(int hostproc, MPI_Comm comm, int &ierr) {
void *mem_ptr;
if (apiCuda()) {
#ifdef DKS_CUDA
cudaError cerror;
cudaIpcMemHandle_t rhandle;
MPI_Recv(&rhandle, sizeof(cudaIpcMemHandle_t), MPI_BYTE, hostproc, 100, comm, NULL);
cerror = cudaIpcOpenMemHandle(&mem_ptr, rhandle, cudaIpcMemLazyEnablePeerAccess);
if (cerror != cudaSuccess) {
DEBUG_MSG("Error opening received handle");
ierr = DKS_ERROR;
}
#endif
return mem_ptr;
}
else if (apiOpenMP()) {
#ifdef DKS_MIC
//BENI:
DEBUG_MSG("No ReceivePointer for MIC is implemented");
return DKS_SUCCESS;
#endif
return mem_ptr;
}
else {
ierr = DKS_ERROR;
DEBUG_MSG("Receive device pointer not implemented for selected platform");
return mem_ptr;
}
}
#endif
/* close received handle */
int DKSBase::closeHandle(void *mem_ptr) {
if (apiCuda()) {
#ifdef DKS_CUDA
cudaError cerror;
cerror = cudaIpcCloseMemHandle(mem_ptr);
if (cerror != cudaSuccess) {
DEBUG_MSG("Error closing memory handle");
return DKS_ERROR;
}
return DKS_SUCCESS;
#endif
}
DEBUG_MSG("Memory handles not implemented for selected platform");
return DKS_ERROR;
}
/* sync device calls */
int DKSBase::syncDevice() {
if (apiCuda())
return CUDA_SAFECALL( cbase->cuda_syncDevice() );
else if (apiOpenMP())
return MIC_SAFECALL( micbase->mic_syncDevice() );
return DKS_ERROR;
}
int DKSBase::callCreateRandomNumbers(void *mem_ptr, int size) {
if (apiCuda())
return CUDA_SAFECALL(cbase->cuda_createRandomNumbers(mem_ptr, size));
if (apiOpenCL())
return OPENCL_SAFECALL(oclbase->ocl_createRandomNumbers(mem_ptr, size));
return DKS_ERROR;
}
int DKSBase::callInitRandoms(int size, int seed) {
if (apiCuda())
return CUDA_SAFECALL(cbase->cuda_createCurandStates(size, seed));
else if (apiOpenCL())
return OPENCL_SAFECALL(oclbase->ocl_createRndStates(size));
else if (apiOpenMP())
return MIC_SAFECALL(micbase->mic_createRandStreams(size));
DEBUG_MSG("No implementation for selceted platform");
return DKS_ERROR;
}