Commit be771f52 authored by Dominik Charousset's avatar Dominik Charousset

Remove OpenCL binding from core library

The OpenCL binding will be moved to its own repository.
parent 5c242b5f
This diff is collapsed.
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_OPENCL_COMMAND_HPP
#define CPPA_OPENCL_COMMAND_HPP
#include <vector>
#include <numeric>
#include <algorithm>
#include <functional>
#include "cppa/opencl/global.hpp"
#include "cppa/abstract_actor.hpp"
#include "cppa/response_promise.hpp"
#include "cppa/opencl/smart_ptr.hpp"
#include "cppa/detail/logging.hpp"
#include "cppa/detail/scope_guard.hpp"
namespace cppa {
namespace opencl {
template<typename T, typename R>
class command : public ref_counted {
public:
command(response_promise handle,
intrusive_ptr<T> actor_facade,
std::vector<cl_event> events,
std::vector<mem_ptr> arguments,
size_t result_size,
message msg)
: m_result_size(result_size)
, m_handle(handle)
, m_actor_facade(actor_facade)
, m_queue(actor_facade->m_queue)
, m_events(std::move(events))
, m_arguments(std::move(arguments))
, m_result(m_result_size)
, m_msg(msg) { }
~command() {
cl_int err{0};
for(auto& e : m_events) {
err = clReleaseEvent(e);
if (err != CL_SUCCESS) {
CPPA_LOGMF(CPPA_ERROR, "clReleaseEvent: "
<< get_opencl_error(err));
}
}
}
void enqueue () {
CPPA_LOG_TRACE("command::enqueue()");
this->ref(); // reference held by the OpenCL comand queue
cl_int err{0};
cl_event event_k;
auto data_or_nullptr = [](const dim_vec& vec) {
return vec.empty() ? nullptr : vec.data();
};
err = clEnqueueNDRangeKernel(m_queue.get(),
m_actor_facade->m_kernel.get(),
m_actor_facade->m_global_dimensions.size(),
data_or_nullptr(m_actor_facade->m_global_offsets),
data_or_nullptr(m_actor_facade->m_global_dimensions),
data_or_nullptr(m_actor_facade->m_local_dimensions),
m_events.size(),
(m_events.empty() ? nullptr : m_events.data()),
&event_k);
if (err != CL_SUCCESS) {
CPPA_LOGMF(CPPA_ERROR, "clEnqueueNDRangeKernel: "
<< get_opencl_error(err));
this->deref(); // or can anything actually happen?
return;
}
else {
cl_event event_r;
err = clEnqueueReadBuffer(m_queue.get(),
m_arguments.back().get(),
CL_FALSE,
0,
sizeof(typename R::value_type) * m_result_size,
m_result.data(),
1,
&event_k,
&event_r);
if (err != CL_SUCCESS) {
throw std::runtime_error("clEnqueueReadBuffer: "
+ get_opencl_error(err));
this->deref(); // failed to enqueue command
return;
}
err = clSetEventCallback(event_r,
CL_COMPLETE,
[](cl_event, cl_int, void* data) {
auto cmd = reinterpret_cast<command*>(data);
cmd->handle_results();
cmd->deref();
},
this);
if (err != CL_SUCCESS) {
CPPA_LOGMF(CPPA_ERROR, "clSetEventCallback: "
<< get_opencl_error(err));
this->deref(); // callback is not set
return;
}
err = clFlush(m_queue.get());
if (err != CL_SUCCESS) {
CPPA_LOGMF(CPPA_ERROR, "clFlush: " << get_opencl_error(err));
}
m_events.push_back(std::move(event_k));
m_events.push_back(std::move(event_r));
}
}
private:
int m_result_size;
response_promise m_handle;
intrusive_ptr<T> m_actor_facade;
command_queue_ptr m_queue;
std::vector<cl_event> m_events;
std::vector<mem_ptr> m_arguments;
R m_result;
message m_msg; // required to keep the argument buffers alive (for async copy)
void handle_results () {
m_handle.deliver(m_actor_facade->m_map_result(m_result));
}
};
} // namespace opencl
} // namespace cppa
#endif // CPPA_OPENCL_COMMAND_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_OPENCL_DEVICE_INFO_HPP
#define CPPA_OPENCL_DEVICE_INFO_HPP
#include "cppa/opencl/global.hpp"
#include "cppa/opencl/program.hpp"
#include "cppa/opencl/smart_ptr.hpp"
namespace cppa {
namespace opencl {
class device_info {
friend class program;
public:
device_info(device_ptr device,
command_queue_ptr queue,
size_t work_group_size,
cl_uint dimensons,
const dim_vec& items_per_dimension)
: m_max_work_group_size(work_group_size)
, m_max_dimensions(dimensons)
, m_max_work_items_per_dim(items_per_dimension)
, m_device(device)
, m_cmd_queue(queue) { }
inline size_t get_max_work_group_size();
inline cl_uint get_max_dimensions();
inline dim_vec get_max_work_items_per_dim();
private:
size_t m_max_work_group_size;
cl_uint m_max_dimensions;
dim_vec m_max_work_items_per_dim;
device_ptr m_device;
command_queue_ptr m_cmd_queue;
};
/******************************************************************************\
* implementation of inline member functions *
\******************************************************************************/
inline size_t device_info::get_max_work_group_size() {
return m_max_work_group_size;
}
inline cl_uint device_info::get_max_dimensions() {
return m_max_dimensions;
}
inline dim_vec device_info::get_max_work_items_per_dim() {
return m_max_work_items_per_dim;
}
} // namespace opencl
} // namespace cppa
#endif // CPPA_OPENCL_DEVICE_INFO_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_OPENCL_GLOBAL_HPP
#define CPPA_OPENCL_GLOBAL_HPP
#include <string>
#include "cppa/detail/limited_vector.hpp"
#if defined __APPLE__ || defined(MACOSX)
#include <OpenCL/opencl.h>
#else
#include <CL/opencl.h>
#endif
namespace cppa {
namespace opencl {
/**
* @brief A vector of up to three elements used for OpenCL dimensions.
*/
using dim_vec = detail::limited_vector<size_t, 3>;
std::string get_opencl_error(cl_int err);
cl_int clReleaseDeviceDummy (cl_device_id);
cl_int clRetainDeviceDummy (cl_device_id);
} // namespace opencl
} // namespace cppa
#endif // CPPA_OPENCL_GLOBAL_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_OPENCL_METAINFO_HPP
#define CPPA_OPENCL_METAINFO_HPP
#include <atomic>
#include <vector>
#include <algorithm>
#include <functional>
#include "cppa/cppa.hpp"
#include "cppa/opencl/global.hpp"
#include "cppa/opencl/program.hpp"
#include "cppa/opencl/smart_ptr.hpp"
#include "cppa/opencl/device_info.hpp"
#include "cppa/opencl/actor_facade.hpp"
#include "cppa/detail/singleton_mixin.hpp"
#include "cppa/detail/singleton_manager.hpp"
namespace cppa {
namespace opencl {
class opencl_metainfo {
friend class program;
friend class detail::singleton_manager;
friend command_queue_ptr get_command_queue(uint32_t id);
public:
const std::vector<device_info> get_devices() const;
private:
static inline opencl_metainfo* create_singleton() {
return new opencl_metainfo;
}
void initialize();
void dispose();
void stop();
context_ptr m_context;
std::vector<device_info> m_devices;
};
opencl_metainfo* get_opencl_metainfo();
} // namespace opencl
} // namespace cppa
#endif // CPPA_OPENCL_METAINFO_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_OPENCL_PROGRAM_HPP
#define CPPA_OPENCL_PROGRAM_HPP
#include <memory>
#include "cppa/opencl/global.hpp"
#include "cppa/opencl/smart_ptr.hpp"
namespace cppa {
namespace opencl {
template<typename Signature>
class actor_facade;
/**
* @brief A wrapper for OpenCL's cl_program.
*/
class program {
template<typename Signature>
friend class actor_facade;
public:
/**
* @brief Factory method, that creates a cppa::opencl::program
* from a given @p kernel_source.
* @returns A program object.
*/
static program create(const char* kernel_source, const char* options = nullptr, uint32_t device_id = 0);
private:
program(context_ptr context, command_queue_ptr queue, program_ptr program);
context_ptr m_context;
program_ptr m_program;
command_queue_ptr m_queue;
};
} // namespace opencl
} // namespace cppa
#endif // CPPA_OPENCL_PROGRAM_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef CPPA_OPENCL_SMART_PTR_HPP
#define CPPA_OPENCL_SMART_PTR_HPP
#include <memory>
#include <algorithm>
#include <type_traits>
namespace cppa {
namespace opencl {
template<typename T, cl_int (*ref)(T), cl_int (*deref)(T)>
class smart_ptr {
using element_type = typename std::remove_pointer<T>::type;
using pointer = element_type* ;
using reference = element_type& ;
using const_pointer = const element_type*;
using const_reference = const element_type&;
public:
smart_ptr(pointer ptr = nullptr) : m_ptr(ptr) {
if (m_ptr) ref(m_ptr);
}
~smart_ptr() { reset(); }
smart_ptr(const smart_ptr& other) : m_ptr(other.m_ptr) {
if (m_ptr) ref(m_ptr);
}
smart_ptr(smart_ptr&& other) : m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
smart_ptr& operator=(pointer ptr) {
reset(ptr);
return *this;
}
smart_ptr& operator=(smart_ptr&& other) {
std::swap(m_ptr, other.m_ptr);
return *this;
}
smart_ptr& operator=(const smart_ptr& other) {
smart_ptr tmp{other};
std::swap(m_ptr, tmp.m_ptr);
return *this;
}
inline void reset(pointer ptr = nullptr) {
if (m_ptr) deref(m_ptr);
m_ptr = ptr;
if (ptr) ref(ptr);
}
// does not modify reference count of ptr
inline void adopt(pointer ptr) {
reset();
m_ptr = ptr;
}
inline pointer get() const { return m_ptr; }
inline pointer operator->() const { return m_ptr; }
inline reference operator*() const { return *m_ptr; }
inline bool operator!() const { return m_ptr == nullptr; }
inline explicit operator bool() const { return m_ptr != nullptr; }
private:
pointer m_ptr;
};
using mem_ptr = smart_ptr<cl_mem, clRetainMemObject, clReleaseMemObject>;
using event_ptr = smart_ptr<cl_event, clRetainEvent, clReleaseEvent> ;
using kernel_ptr = smart_ptr<cl_kernel, clRetainKernel, clReleaseKernel> ;
using context_ptr = smart_ptr<cl_context, clRetainContext, clReleaseContext>;
using program_ptr = smart_ptr<cl_program, clRetainProgram, clReleaseProgram>;
typedef smart_ptr<cl_device_id, clRetainDeviceDummy, clReleaseDeviceDummy>
device_ptr;
typedef smart_ptr<cl_command_queue, clRetainCommandQueue, clReleaseCommandQueue>
command_queue_ptr;
} // namespace opencl
} // namespace cppa
#endif // CPPA_OPENCL_SMART_PTR_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#include "cppa/opencl/global.hpp"
namespace cppa {
namespace opencl {
std::string get_opencl_error(cl_int err) {
switch (err) {
case CL_SUCCESS:
return "CL_SUCCESS";
case CL_DEVICE_NOT_FOUND:
return "CL_DEVICE_NOT_FOUND";
case CL_DEVICE_NOT_AVAILABLE:
return "CL_DEVICE_NOT_AVAILABLE";
case CL_COMPILER_NOT_AVAILABLE:
return "CL_COMPILER_NOT_AVAILABLE";
case CL_MEM_OBJECT_ALLOCATION_FAILURE:
return "CL_MEM_OBJECT_ALLOCATION_FAILURE";
case CL_OUT_OF_RESOURCES:
return "CL_OUT_OF_RESOURCES";
case CL_OUT_OF_HOST_MEMORY:
return "CL_OUT_OF_HOST_MEMORY";
case CL_PROFILING_INFO_NOT_AVAILABLE:
return "CL_PROFILING_INFO_NOT_AVAILABLE";
case CL_MEM_COPY_OVERLAP:
return "CL_MEM_COPY_OVERLAP";
case CL_IMAGE_FORMAT_MISMATCH:
return "CL_IMAGE_FORMAT_MISMATCH";
case CL_IMAGE_FORMAT_NOT_SUPPORTED:
return "CL_IMAGE_FORMAT_NOT_SUPPORTED";
case CL_BUILD_PROGRAM_FAILURE:
return "CL_BUILD_PROGRAM_FAILURE";
case CL_MAP_FAILURE:
return "CL_MAP_FAILURE";
case CL_INVALID_VALUE:
return "CL_INVALID_VALUE";
case CL_INVALID_DEVICE_TYPE:
return "CL_INVALID_DEVICE_TYPE";
case CL_INVALID_PLATFORM:
return "CL_INVALID_PLATFORM";
case CL_INVALID_DEVICE:
return "CL_INVALID_DEVICE";
case CL_INVALID_CONTEXT:
return "CL_INVALID_CONTEXT";
case CL_INVALID_QUEUE_PROPERTIES:
return "CL_INVALID_QUEUE_PROPERTIES";
case CL_INVALID_COMMAND_QUEUE:
return "CL_INVALID_COMMAND_QUEUE";
case CL_INVALID_HOST_PTR:
return "CL_INVALID_HOST_PTR";
case CL_INVALID_MEM_OBJECT:
return "CL_INVALID_MEM_OBJECT";
case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
case CL_INVALID_IMAGE_SIZE:
return "CL_INVALID_IMAGE_SIZE";
case CL_INVALID_SAMPLER:
return "CL_INVALID_SAMPLER";
case CL_INVALID_BINARY:
return "CL_INVALID_BINARY";
case CL_INVALID_BUILD_OPTIONS:
return "CL_INVALID_BUILD_OPTIONS";
case CL_INVALID_PROGRAM:
return "CL_INVALID_PROGRAM";
case CL_INVALID_PROGRAM_EXECUTABLE:
return "CL_INVALID_PROGRAM_EXECUTABLE";
case CL_INVALID_KERNEL_NAME:
return "CL_INVALID_KERNEL_NAME";
case CL_INVALID_KERNEL_DEFINITION:
return "CL_INVALID_KERNEL_DEFINITION";
case CL_INVALID_KERNEL:
return "CL_INVALID_KERNEL";
case CL_INVALID_ARG_INDEX:
return "CL_INVALID_ARG_INDEX";
case CL_INVALID_ARG_VALUE:
return "CL_INVALID_ARG_VALUE";
case CL_INVALID_ARG_SIZE:
return "CL_INVALID_ARG_SIZE";
case CL_INVALID_KERNEL_ARGS:
return "CL_INVALID_KERNEL_ARGS";
case CL_INVALID_WORK_DIMENSION:
return "CL_INVALID_WORK_DIMENSION";
case CL_INVALID_WORK_GROUP_SIZE:
return "CL_INVALID_WORK_GROUP_SIZE";
case CL_INVALID_WORK_ITEM_SIZE:
return "CL_INVALID_WORK_ITEM_SIZE";
case CL_INVALID_GLOBAL_OFFSET:
return "CL_INVALID_GLOBAL_OFFSET";
case CL_INVALID_EVENT_WAIT_LIST:
return "CL_INVALID_EVENT_WAIT_LIST";
case CL_INVALID_EVENT:
return "CL_INVALID_EVENT";
case CL_INVALID_OPERATION:
return "CL_INVALID_OPERATION";
case CL_INVALID_GL_OBJECT:
return "CL_INVALID_GL_OBJECT";
case CL_INVALID_BUFFER_SIZE:
return "CL_INVALID_BUFFER_SIZE";
case CL_INVALID_MIP_LEVEL:
return "CL_INVALID_MIP_LEVEL";
case CL_INVALID_GLOBAL_WORK_SIZE:
return "CL_INVALID_GLOBAL_WORK_SIZE";
default: return "UNKNOWN_ERROR";
}
}
cl_int clReleaseDeviceDummy (cl_device_id) { return 0; }
cl_int clRetainDeviceDummy (cl_device_id) { return 0; }
} // namespace opencl
} // namespace cppa
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#include "cppa/opencl/opencl_metainfo.hpp"
using namespace std;
namespace cppa {
namespace opencl {
const std::vector<device_info> opencl_metainfo::get_devices() const {
return m_devices;
}
void opencl_metainfo::initialize() {
cl_int err{0};
// get number of available platforms
cl_uint number_of_platforms;
err = clGetPlatformIDs(0, nullptr, &number_of_platforms);
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clGetPlatformIDs (getting number of platforms): "
<< get_opencl_error(err);
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw logic_error(oss.str());
}
// get platform ids
vector<cl_platform_id> ids(number_of_platforms);
err = clGetPlatformIDs(ids.size(), ids.data(), nullptr);
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clGetPlatformIDs (getting platform ids): "
<< get_opencl_error(err);
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw logic_error(oss.str());
}
// find gpu devices on our platform
int pid{0};
cl_uint num_devices{0};
cl_device_type dev_type{CL_DEVICE_TYPE_GPU};
err = clGetDeviceIDs(ids[pid], dev_type, 0, nullptr, &num_devices);
if (err == CL_DEVICE_NOT_FOUND) {
CPPA_LOG_TRACE("No gpu devices found. Looking for cpu devices.");
cout << "No gpu devices found. Looking for cpu devices." << endl;
dev_type = CL_DEVICE_TYPE_CPU;
err = clGetDeviceIDs(ids[pid], dev_type, 0, nullptr, &num_devices);
}
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clGetDeviceIDs: " << get_opencl_error(err);
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw runtime_error(oss.str());
}
vector<cl_device_id> devices(num_devices);
err = clGetDeviceIDs(ids[pid], dev_type, num_devices, devices.data(), nullptr);
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clGetDeviceIDs: " << get_opencl_error(err);
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw runtime_error(oss.str());
}
// create a context
m_context.adopt(clCreateContext(0,
devices.size(),
devices.data(),
nullptr,
nullptr,
&err));
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clCreateContext: " << get_opencl_error(err);
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw runtime_error(oss.str());
}
// create command queues
for (auto& d : devices) {
CPPA_LOG_TRACE("Creating command queue for device(s).");
device_ptr device;
device.adopt(d);
size_t return_size{0};
static constexpr size_t buf_size = 128;
char buf[buf_size];
err = clGetDeviceInfo(device.get(), CL_DEVICE_NAME, buf_size, buf, &return_size);
if (err != CL_SUCCESS) {
CPPA_LOGMF(CPPA_ERROR, "clGetDeviceInfo (CL_DEVICE_NAME): "
<< get_opencl_error(err));
fill(buf, buf+buf_size, 0);
}
command_queue_ptr cmd_queue;
cmd_queue.adopt(clCreateCommandQueue(m_context.get(),
device.get(),
CL_QUEUE_PROFILING_ENABLE,
&err));
if (err != CL_SUCCESS) {
CPPA_LOGMF(CPPA_DEBUG, "Could not create command queue for device "
<< buf << ": " << get_opencl_error(err));
}
else {
size_t max_work_group_size{0};
err = clGetDeviceInfo(device.get(),
CL_DEVICE_MAX_WORK_GROUP_SIZE,
sizeof(size_t),
&max_work_group_size,
&return_size);
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clGetDeviceInfo ("
<< "CL_DEVICE_MAX_WORK_GROUP_SIZE): "
<< get_opencl_error(err);
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw runtime_error(oss.str());
}
cl_uint max_work_item_dimensions = 0;
err = clGetDeviceInfo(device.get(),
CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,
sizeof(cl_uint),
&max_work_item_dimensions,
&return_size);
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clGetDeviceInfo ("
<< "CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS): "
<< get_opencl_error(err);
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw runtime_error(oss.str());
}
dim_vec max_work_items_per_dim(max_work_item_dimensions);
err = clGetDeviceInfo(device.get(),
CL_DEVICE_MAX_WORK_ITEM_SIZES,
sizeof(size_t)*max_work_item_dimensions,
max_work_items_per_dim.data(),
&return_size);
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clGetDeviceInfo ("
<< "CL_DEVICE_MAX_WORK_ITEM_SIZES): "
<< get_opencl_error(err);
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw runtime_error(oss.str());
}
device_info dev_info{device,
cmd_queue,
max_work_group_size,
max_work_item_dimensions,
max_work_items_per_dim};
m_devices.push_back(move(dev_info));
}
}
if (m_devices.empty()) {
ostringstream oss;
oss << "Could not create a command queue for "
<< "any present device.";
CPPA_LOGMF(CPPA_ERROR, oss.str());
throw runtime_error(oss.str());
}
}
void opencl_metainfo::destroy() {
delete this;
}
void opencl_metainfo::dispose() {
delete this;
}
opencl_metainfo* get_opencl_metainfo() {
return detail::singleton_manager::get_opencl_metainfo();
}
} // namespace opencl
} // namespace cppa
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011-2014 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* Raphael Hiesgen <raphael.hiesgen@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include "cppa/config.hpp"
#include "cppa/opencl/program.hpp"
#include "cppa/opencl/opencl_metainfo.hpp"
#include "cppa/detail/singletons.hpp"
using namespace std;
namespace cppa {
namespace opencl {
program::program(context_ptr context, command_queue_ptr queue, program_ptr program)
: m_context(move(context)), m_program(move(program)), m_queue(move(queue)) { }
program program::create(const char* kernel_source, const char* options, uint32_t device_id) {
auto metainfo = get_opencl_metainfo();
auto devices = metainfo->get_devices();
auto context = metainfo->m_context;
if (devices.size() <= device_id) {
ostringstream oss;
oss << "Device id " << device_id
<< " is not a vaild device. Maximum id is: "
<< (devices.size() -1) << ".";
CPPA_LOGM_ERROR(detail::demangle<program>().c_str(), oss.str());
throw runtime_error(oss.str());
}
cl_int err{0};
// create program object from kernel source
size_t kernel_source_length = strlen(kernel_source);
program_ptr pptr;
pptr.adopt(clCreateProgramWithSource(context.get(),
1,
&kernel_source,
&kernel_source_length,
&err));
if (err != CL_SUCCESS) {
throw runtime_error("clCreateProgramWithSource: "
+ get_opencl_error(err));
}
// build programm from program object
auto dev_tmp = devices[device_id].m_device.get();
err = clBuildProgram(pptr.get(), 1, &dev_tmp, options, nullptr, nullptr);
if (err != CL_SUCCESS) {
ostringstream oss;
oss << "clBuildProgram: " << get_opencl_error(err);
// get the build log
if (err == CL_BUILD_PROGRAM_FAILURE) {
size_t buildlog_buffer_size = 0;
// get the log length
clGetProgramBuildInfo(pptr.get(),
dev_tmp,
CL_PROGRAM_BUILD_LOG,
sizeof(buildlog_buffer_size),
nullptr,
&buildlog_buffer_size);
vector<char> buffer(buildlog_buffer_size);
// fill the buffer with buildlog informations
clGetProgramBuildInfo(pptr.get(),
dev_tmp,
CL_PROGRAM_BUILD_LOG,
sizeof(buffer[0]) * buildlog_buffer_size,
buffer.data(),
nullptr);
// make sure string is null terminated
buffer.push_back('\0');
cerr << "OpenCL build error log: "
<< endl
<< buffer.data()
<< endl;
}
throw runtime_error(oss.str());
}
return {context, devices[device_id].m_cmd_queue, pptr};
}
} // namespace opencl
} // namespace cppa
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment