Code quality: more cleaning of files architecture

This commit is contained in:
Philippe Tillet
2015-08-06 19:34:26 -07:00
parent 0f0946b7a7
commit 33fea11547
57 changed files with 106 additions and 115 deletions

View File

@@ -0,0 +1,25 @@
#include "core.h"
#include "driver.h"
#include "exceptions.h"
#include "model.h"
#include <boost/python.hpp>
#include <boost/numpy.hpp>
namespace bp = boost::python;
namespace np = boost::numpy;
BOOST_PYTHON_MODULE(_isaac)
{
Py_Initialize();
np::initialize();
// specify that this module is actually a package
bp::object package = bp::scope();
package.attr("__path__") = "_isaac";
export_driver();
export_exceptions();
export_templates();
export_core();
}

View File

@@ -0,0 +1,91 @@
#ifndef ISAAC_PYTHON_COMMON_HPP
#define ISAAC_PYTHON_COMMON_HPP
#include <boost/python.hpp>
#include <boost/numpy.hpp>
#include <boost/numpy/dtype.hpp>
#include "isaac/array.h"
#define MAP_ENUM(v, ns) .value(#v, ns::v)
namespace bp = boost::python;
namespace isc = isaac;
namespace np = boost::numpy;
namespace tools
{
template<class IT>
bp::list to_list(IT const & begin, IT const & end)
{
bp::list res;
for (IT it = begin; it != end; ++it)
res.append(*it);
return res;
}
template<class T>
std::vector<T> to_vector(bp::list const & list)
{
std::size_t len = bp::len(list);
std::vector<T> res; res.reserve(len);
for(std::size_t i = 0 ; i < len ; ++i)
res.push_back(boost::python::extract<T>(list[i]));
return res;
}
inline isc::numeric_type extract_dtype(bp::object const & odtype)
{
std::string name = bp::extract<std::string>(odtype.attr("__class__").attr("__name__"))();
if(name=="class")
name = bp::extract<std::string>(odtype.attr("__name__"))();
else
name = bp::extract<std::string>(odtype.attr("__class__").attr("__name__"))();
if(name=="int8") return isc::CHAR_TYPE;
else if(name=="uint8") return isc::UCHAR_TYPE;
else if(name=="int16") return isc::SHORT_TYPE;
else if(name=="uint16") return isc::USHORT_TYPE;
else if(name=="int32") return isc::INT_TYPE;
else if(name=="uint32") return isc::UINT_TYPE;
else if(name=="int64") return isc::LONG_TYPE;
else if(name=="uint64") return isc::ULONG_TYPE;
else if(name=="float32") return isc::FLOAT_TYPE;
else if(name=="float64") return isc::DOUBLE_TYPE;
else
{
PyErr_SetString(PyExc_TypeError, "Data type not understood");
bp::throw_error_already_set();
throw;
}
}
inline isc::expression_type extract_template_type(bp::object const & odtype)
{
std::string name = bp::extract<std::string>(odtype.attr("__class__").attr("__name__"))();
if(name=="class")
name = bp::extract<std::string>(odtype.attr("__name__"))();
else
name = bp::extract<std::string>(odtype.attr("__class__").attr("__name__"))();
if(name=="axpy") return isc::AXPY_TYPE;
else if(name=="ger") return isc::GER_TYPE;
else if(name=="dot") return isc::DOT_TYPE;
else if(name=="gemv_n") return isc::GEMV_N_TYPE;
else if(name=="gemm_t") return isc::GEMV_T_TYPE;
else if(name=="gemm_nn") return isc::GEMM_NN_TYPE;
else if(name=="gemm_tn") return isc::GEMM_TN_TYPE;
else if(name=="gemm_nt") return isc::GEMM_NT_TYPE;
else if(name=="gemm_tt") return isc::GEMM_TT_TYPE;
else
{
PyErr_SetString(PyExc_TypeError, "Template type not understood");
bp::throw_error_already_set();
throw;
}
}
}
#endif

355
python/src/bind/core.cpp Normal file
View File

@@ -0,0 +1,355 @@
#include "isaac/model/model.h"
#include "common.hpp"
#include "core.h"
namespace detail
{
isc::numeric_type to_isc_dtype(np::dtype const & T)
{
if(T==np::detail::get_int_dtype<8, false>()) return isc::CHAR_TYPE;
else if(T==np::detail::get_int_dtype<8, true>()) return isc::UCHAR_TYPE;
else if(T==np::detail::get_int_dtype<16, false>()) return isc::SHORT_TYPE;
else if(T==np::detail::get_int_dtype<16, true>()) return isc::USHORT_TYPE;
else if(T==np::detail::get_int_dtype<32, false>()) return isc::INT_TYPE;
else if(T==np::detail::get_int_dtype<32, true>()) return isc::UINT_TYPE;
else if(T==np::detail::get_int_dtype<64, false>()) return isc::LONG_TYPE;
else if(T==np::detail::get_int_dtype<64, true>()) return isc::ULONG_TYPE;
// else if(T==np::detail::get_float_dtype<16>()) return isc::HALF_TYPE;
else if(T==np::detail::get_float_dtype<32>()) return isc::FLOAT_TYPE;
else if(T==np::detail::get_float_dtype<64>()) return isc::DOUBLE_TYPE;
else{
PyErr_SetString(PyExc_TypeError, "Unrecognized datatype");
bp::throw_error_already_set();
throw; // suppress warning; throw_error_already_set() never returns but isn't marked noreturn: https://svn.boost.org/trac/boost/ticket/1482
}
}
np::dtype to_np_dtype(isc::numeric_type const & T) throw()
{
if(T==isc::CHAR_TYPE) return np::detail::get_int_dtype<8, false>();
else if(T==isc::UCHAR_TYPE) return np::detail::get_int_dtype<8, true>();
else if(T==isc::SHORT_TYPE) return np::detail::get_int_dtype<16, false>();
else if(T==isc::USHORT_TYPE) return np::detail::get_int_dtype<16, true>();
else if(T==isc::INT_TYPE) return np::detail::get_int_dtype<32, false>();
else if(T==isc::UINT_TYPE) return np::detail::get_int_dtype<32, true>();
else if(T==isc::LONG_TYPE) return np::detail::get_int_dtype<64, false>();
else if(T==isc::ULONG_TYPE) return np::detail::get_int_dtype<64, true>();
// else if(T==isc::HALF_TYPE) return np::detail::get_float_dtype<16>();
else if(T==isc::FLOAT_TYPE) return np::detail::get_float_dtype<32>();
else if(T==isc::DOUBLE_TYPE) return np::detail::get_float_dtype<64>();
else{
PyErr_SetString(PyExc_TypeError, "Unrecognized datatype");
bp::throw_error_already_set();
throw; // suppress warning; throw_error_already_set() never returns but isn't marked noreturn: https://svn.boost.org/trac/boost/ticket/1482
}
}
bp::tuple get_shape(isc::array const & x)
{
return bp::make_tuple(x.shape()[0], x.shape()[1]);
}
template<class T>
struct datatype : public isc::value_scalar
{
datatype(T t) : isc::value_scalar(t){ }
};
template<class T>
unsigned int size(datatype<T> const & dt)
{ return isc::size_of(dt.dtype()) ; }
#define INSTANTIATE(name, clname) \
struct name : public detail::datatype<clname> { name(clname value) : detail::datatype<clname>(value){} };
INSTANTIATE(int8, cl_char)
INSTANTIATE(uint8, cl_uchar)
INSTANTIATE(int16, cl_short)
INSTANTIATE(uint16, cl_ushort)
INSTANTIATE(int32, cl_int)
INSTANTIATE(uint32, cl_uint)
INSTANTIATE(int64, cl_long)
INSTANTIATE(uint64, cl_ulong)
INSTANTIATE(float32, cl_float)
INSTANTIATE(float64, cl_double)
#undef INSTANTIATE
}
namespace detail
{
std::shared_ptr<isc::model> construct_model(bp::object dtype, bp::object const & tp, isc::driver::CommandQueue & queue)
{
return std::shared_ptr<isc::model>(new isc::model(tools::extract_template_type(tp), tools::extract_dtype(dtype), (isaac::templates::base const &)bp::extract<isaac::templates::base>(tp), queue));
}
std::shared_ptr<isc::array>
ndarray_to_iscarray(const np::ndarray& array, isc::driver::Context const & ctx)
{
int d = array.get_nd();
if (d > 2) {
PyErr_SetString(PyExc_TypeError, "Only 1-D and 2-D arrays are supported!");
bp::throw_error_already_set();
}
isc::numeric_type dtype = to_isc_dtype(array.get_dtype());
isc::int_t size = (isc::int_t)array.shape(0);
isc::array* v = new isc::array(size, dtype, ctx);
void* data = (void*)array.get_data();
isc::copy(data, *v);
return std::shared_ptr<isc::array>(v);
}
std::shared_ptr<isc::array> create_array(bp::object const & obj, bp::object odtype, isc::driver::Context const & context)
{
return ndarray_to_iscarray(np::from_object(obj, to_np_dtype(tools::extract_dtype(odtype))), context);
}
std::shared_ptr<isc::array> create_zeros_array(isc::int_t M, isc::int_t N, bp::object odtype, isc::driver::Context const & context)
{
return std::shared_ptr<isc::array>(new isc::array(isc::zeros(M, N, tools::extract_dtype(odtype), context)));
}
std::shared_ptr<isc::array> create_empty_array(bp::object sizes, bp::object odtype, isc::driver::Context const & context)
{
typedef std::shared_ptr<isc::array> result_type;
std::size_t len;
int size1;
int size2;
try{
len = bp::len(sizes);
size1 = bp::extract<int>(sizes[0])();
size2 = bp::extract<int>(sizes[1])();
}catch(bp::error_already_set const &){
PyErr_Clear();
len = 1;
size1 = bp::extract<int>(sizes)();
}
isc::numeric_type dtype = tools::extract_dtype(odtype);
if(len < 1 || len > 2)
{
PyErr_SetString(PyExc_TypeError, "Only 1-D and 2-D arrays are supported!");
bp::throw_error_already_set();
}
if(len==1)
return result_type(new isc::array(size1, dtype, context));
return result_type(new isc::array(size1, size2, dtype, context));
}
std::string type_name(bp::object const & obj)
{
std::string name = bp::extract<std::string>(obj.attr("__class__").attr("__name__"))();
if(name=="class")
return bp::extract<std::string>(obj.attr("__name__"))();
else
return bp::extract<std::string>(obj.attr("__class__").attr("__name__"))();
}
std::shared_ptr<isc::scalar> construct_scalar(bp::object obj, isc::driver::Context const & context)
{
typedef std::shared_ptr<isc::scalar> result_type;
std::string name = type_name(obj);
if(name=="int") return result_type(new isc::scalar(bp::extract<int>(obj)(), context));
else if(name=="float") return result_type(new isc::scalar(bp::extract<double>(obj)(), context));
else if(name=="long") return result_type(new isc::scalar(bp::extract<long>(obj)(), context));
else if(name=="int") return result_type(new isc::scalar(bp::extract<int>(obj)(), context));
else if(name=="int8") return result_type(new isc::scalar(isc::CHAR_TYPE, context));
else if(name=="uint8") return result_type(new isc::scalar(isc::UCHAR_TYPE, context));
else if(name=="int16") return result_type(new isc::scalar(isc::SHORT_TYPE, context));
else if(name=="uint16") return result_type(new isc::scalar(isc::USHORT_TYPE, context));
else if(name=="int32") return result_type(new isc::scalar(isc::INT_TYPE, context));
else if(name=="uint32") return result_type(new isc::scalar(isc::UINT_TYPE, context));
else if(name=="int64") return result_type(new isc::scalar(isc::LONG_TYPE, context));
else if(name=="uint64") return result_type(new isc::scalar(isc::ULONG_TYPE, context));
else if(name=="float32") return result_type(new isc::scalar(isc::FLOAT_TYPE, context));
else if(name=="float64") return result_type(new isc::scalar(isc::DOUBLE_TYPE, context));
else{
PyErr_SetString(PyExc_TypeError, "Data type not understood");
bp::throw_error_already_set();
throw;
}
}
}
//////////////
/// EXPORT
/////////////
void export_core()
{
bp::class_<isaac::model>("model", bp::no_init)
.def("__init__", bp::make_constructor(detail::construct_model))
.def("execute", &isc::model::execute);
bp::class_<isc::value_scalar>("value_scalar", bp::no_init)
.add_property("dtype", &isc::value_scalar::dtype);
#define INSTANTIATE(name, clname) \
bp::class_<detail::datatype<clname>, bp::bases<isc::value_scalar> >(#name, bp::init<clname>());\
bp::class_<detail::name, bp::bases<detail::datatype<clname> > >(#name, bp::init<clname>())\
.add_property("size", &detail::size<clname>)\
;
INSTANTIATE(int8, cl_char)
INSTANTIATE(uint8, cl_uchar)
INSTANTIATE(int16, cl_short)
INSTANTIATE(uint16, cl_ushort)
INSTANTIATE(int32, cl_int)
INSTANTIATE(uint32, cl_uint)
INSTANTIATE(int64, cl_long)
INSTANTIATE(uint64, cl_ulong)
INSTANTIATE(float32, cl_float)
INSTANTIATE(float64, cl_double)
#undef INSTANTIATE
bp::enum_<isc::expression_type>("operations")
MAP_ENUM(AXPY_TYPE, isc)
MAP_ENUM(GER_TYPE, isc)
MAP_ENUM(DOT_TYPE, isc)
MAP_ENUM(GEMV_N_TYPE, isc)
MAP_ENUM(GEMV_T_TYPE, isc)
MAP_ENUM(GEMM_NN_TYPE, isc)
MAP_ENUM(GEMM_TN_TYPE, isc)
MAP_ENUM(GEMM_NT_TYPE, isc)
MAP_ENUM(GEMM_TT_TYPE, isc);
#define ADD_SCALAR_HANDLING(OP)\
.def(bp::self OP int())\
.def(bp::self OP long())\
.def(bp::self OP double())\
.def(bp::self OP bp::other<isc::value_scalar>())\
.def(int() OP bp::self)\
.def(long() OP bp::self)\
.def(double() OP bp::self)\
.def(bp::other<isc::value_scalar>() OP bp::self)
#define ADD_ARRAY_OPERATOR(OP)\
.def(bp::self OP bp::self)\
ADD_SCALAR_HANDLING(OP)
bp::class_<isc::expressions_tuple>
("array_expression_container", bp::init<isc::array_expression const &>())
;
bp::class_<isc::array_expression >("array_expression", bp::no_init)
ADD_ARRAY_OPERATOR(+)
ADD_ARRAY_OPERATOR(-)
ADD_ARRAY_OPERATOR(*)
ADD_ARRAY_OPERATOR(/)
ADD_ARRAY_OPERATOR(>)
ADD_ARRAY_OPERATOR(>=)
ADD_ARRAY_OPERATOR(<)
ADD_ARRAY_OPERATOR(<=)
ADD_ARRAY_OPERATOR(==)
ADD_ARRAY_OPERATOR(!=)
.add_property("context", bp::make_function(&isc::array_expression::context, bp::return_internal_reference<>()))
.def(bp::self_ns::abs(bp::self))
// .def(bp::self_ns::pow(bp::self))
;
#undef ADD_ARRAY_OPERATOR
#define ADD_ARRAY_OPERATOR(OP) \
.def(bp::self OP bp::self)\
.def(bp::self OP bp::other<isc::array_expression>())\
.def(bp::other<isc::array_expression>() OP bp::self) \
ADD_SCALAR_HANDLING(OP)
bp::class_<isc::array,
std::shared_ptr<isc::array> >
( "array", bp::no_init)
.def("__init__", bp::make_constructor(detail::create_array, bp::default_call_policies(), (bp::arg("obj"), bp::arg("dtype") = bp::scope().attr("float32"), bp::arg("context")=boost::ref(isc::driver::backend::contexts::get_default()))))
.def(bp::init<isc::array_expression>())
.add_property("dtype", &isc::array::dtype)
.add_property("context", bp::make_function(&isc::array::context, bp::return_internal_reference<>()))
.add_property("T", &isc::array::T)
.add_property("shape", &detail::get_shape)
ADD_ARRAY_OPERATOR(+)
ADD_ARRAY_OPERATOR(-)
ADD_ARRAY_OPERATOR(*)
ADD_ARRAY_OPERATOR(/)
ADD_ARRAY_OPERATOR(>)
ADD_ARRAY_OPERATOR(>=)
ADD_ARRAY_OPERATOR(<)
ADD_ARRAY_OPERATOR(<=)
ADD_ARRAY_OPERATOR(==)
ADD_ARRAY_OPERATOR(!=)
.def(bp::self_ns::abs(bp::self))
// .def(bp::self_ns::pow(bp::self))
.def(bp::self_ns::str(bp::self_ns::self))
;
bp::class_<isc::scalar, bp::bases<isc::array> >
("scalar", bp::no_init)
.def("__init__", bp::make_constructor(detail::construct_scalar, bp::default_call_policies(), (bp::arg(""), bp::arg("context")=boost::ref(isc::driver::backend::contexts::get_default()))))
;
//Other numpy-like initializers
bp::def("empty", &detail::create_empty_array, (bp::arg("shape"), bp::arg("dtype") = bp::scope().attr("float32"), bp::arg("context")=boost::ref(isc::driver::backend::contexts::get_default())));
//Assign
bp::def("assign", static_cast<isc::array_expression (*)(isc::array const &, isc::array const &)>(&isc::assign));\
bp::def("assign", static_cast<isc::array_expression (*)(isc::array const &, isc::array_expression const &)>(&isc::assign));\
//Binary
#define MAP_FUNCTION(name) \
bp::def(#name, static_cast<isc::array_expression (*)(isc::array const &, isc::array const &)>(&isc::name));\
bp::def(#name, static_cast<isc::array_expression (*)(isc::array_expression const &, isc::array const &)>(&isc::name));\
bp::def(#name, static_cast<isc::array_expression (*)(isc::array const &, isc::array_expression const &)>(&isc::name));\
bp::def(#name, static_cast<isc::array_expression (*)(isc::array_expression const &, isc::array_expression const &)>(&isc::name));
MAP_FUNCTION(maximum)
MAP_FUNCTION(minimum)
MAP_FUNCTION(pow)
MAP_FUNCTION(dot)
#undef MAP_FUNCTION
//Unary
#define MAP_FUNCTION(name) \
bp::def(#name, static_cast<isc::array_expression (*)(isc::array const &)>(&isc::name));\
bp::def(#name, static_cast<isc::array_expression (*)(isc::array_expression const &)>(&isc::name));
bp::def("zeros", &detail::create_zeros_array, (bp::arg("shape"), bp::arg("dtype") = bp::scope().attr("float32"), bp::arg("context")=boost::ref(isc::driver::backend::contexts::get_default())));
MAP_FUNCTION(abs)
MAP_FUNCTION(acos)
MAP_FUNCTION(asin)
MAP_FUNCTION(atan)
MAP_FUNCTION(ceil)
MAP_FUNCTION(cos)
MAP_FUNCTION(cosh)
MAP_FUNCTION(exp)
MAP_FUNCTION(floor)
MAP_FUNCTION(log)
MAP_FUNCTION(log10)
MAP_FUNCTION(sin)
MAP_FUNCTION(sinh)
MAP_FUNCTION(sqrt)
MAP_FUNCTION(tan)
MAP_FUNCTION(tanh)
#undef MAP_FUNCTION
/*--- Reduction operators----*/
//---------------------------------------
#define MAP_FUNCTION(name) \
bp::def(#name, static_cast<isc::array_expression (*)(isc::array const &, isc::int_t)>(&isc::name));\
bp::def(#name, static_cast<isc::array_expression (*)(isc::array_expression const &, isc::int_t)>(&isc::name));
MAP_FUNCTION(sum)
MAP_FUNCTION(max)
MAP_FUNCTION(min)
MAP_FUNCTION(argmax)
MAP_FUNCTION(argmin)
#undef MAP_FUNCTION
}

6
python/src/bind/core.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef ISAAC_PYTHON_CORE_HPP
#define ISAAC_PYTHON_CORE_HPP
void export_core();
#endif

193
python/src/bind/driver.cpp Normal file
View File

@@ -0,0 +1,193 @@
#include <memory>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
#include "isaac/model/model.h"
#include "isaac/symbolic/execute.h"
#include "common.hpp"
#include "driver.h"
namespace detail
{
bp::list nv_compute_capability(isc::driver::Device const & device)
{
bp::list res;
std::pair<unsigned int, unsigned int> cc = device.nv_compute_capability();
res.append(cc.first);
res.append(cc.second);
return res;
}
bp::list get_platforms()
{
std::vector<isc::driver::Platform> platforms;
isc::driver::backend::platforms(platforms);
return tools::to_list(platforms.begin(), platforms.end());
}
bp::list get_devices(isc::driver::Platform const & platform)
{
std::vector<isc::driver::Device> devices;
platform.devices(devices);
return tools::to_list(devices.begin(), devices.end());
}
bp::list get_queues(isc::driver::Context const & context)
{
std::vector<isc::driver::CommandQueue*> queues;
isc::driver::backend::queues::get(context, queues);
bp::list res;
for(isc::driver::CommandQueue* queue:queues)
res.append(*queue);
return res;
}
std::shared_ptr< isc::driver::CommandQueue> create_queue(isc::driver::Context const & context, isc::driver::Device const & device)
{
return std::shared_ptr<isc::driver::CommandQueue>(new isc::driver::CommandQueue(context, device));
}
struct model_map_indexing
{
static isc::model& get_item(isc::database::map_type& container, bp::tuple i_)
{
isc::expression_type expression = tools::extract_template_type(i_[0]);
isc::numeric_type dtype = tools::extract_dtype(i_[1]);
isc::database::map_type::iterator i = container.find(std::make_pair(expression, dtype));
if (i == container.end())
{
PyErr_SetString(PyExc_KeyError, "Invalid key");
bp::throw_error_already_set();
}
return *i->second;
}
static void set_item(isc::database::map_type& container, bp::tuple i_, isc::model const & v)
{
isc::expression_type expression = tools::extract_template_type(i_[0]);
isc::numeric_type dtype = tools::extract_dtype(i_[1]);
container[std::make_pair(expression, dtype)].reset(new isc::model(v));
}
};
std::string to_string(isc::driver::device_type type)
{
if(type==isc::driver::DEVICE_TYPE_CPU) return "CPU";
if(type==isc::driver::DEVICE_TYPE_GPU) return "GPU";
if(type==isc::driver::DEVICE_TYPE_ACCELERATOR) return "ACCELERATOR";
throw;
}
std::shared_ptr<isc::driver::Context> make_context(isc::driver::Device const & dev)
{ return std::shared_ptr<isc::driver::Context>(new isc::driver::Context(dev)); }
bp::object enqueue(isc::array_expression const & expression, unsigned int queue_id, bp::list dependencies, bool tune, int label, std::string const & program_name, bool force_recompile)
{
std::list<isc::driver::Event> events;
std::vector<isc::driver::Event> cdependencies = tools::to_vector<isc::driver::Event>(dependencies);
isc::execution_options_type execution_options(queue_id, &events, &cdependencies);
isc::dispatcher_options_type dispatcher_options(tune, label);
isc::compilation_options_type compilation_options(program_name, force_recompile);
isc::array_expression::container_type::value_type root = expression.tree()[expression.root()];
if(isc::detail::is_assignment(root.op))
{
isc::execute(isc::control(expression, execution_options, dispatcher_options, compilation_options), isaac::database::get(execution_options.queue(expression.context())));
return bp::make_tuple(bp::ptr(root.lhs.array), tools::to_list(events.begin(), events.end()));
}
else
{
std::shared_ptr<isc::array> parray(new isc::array(isc::control(expression, execution_options, dispatcher_options, compilation_options)));
return bp::make_tuple(parray, tools::to_list(events.begin(), events.end()));
}
}
}
struct state_type{ };
state_type state;
void export_driver()
{
typedef std::vector<isc::driver::CommandQueue> queues_t;
bp::class_<queues_t>("queues")
.def("__len__", &queues_t::size)
.def("__getitem__", &bp::vector_indexing_suite<queues_t>::get_item, bp::return_internal_reference<>())
.def("__setitem__", &bp::vector_indexing_suite<queues_t>::set_item, bp::with_custodian_and_ward<1,2>())
.def("append", &bp::vector_indexing_suite<queues_t>::append)
;
bp::class_<isc::database::map_type>("models")
.def("__getitem__", &detail::model_map_indexing::get_item, bp::return_internal_reference<>())
.def("__setitem__", &detail::model_map_indexing::set_item, bp::with_custodian_and_ward<1,2>())
;
bp::enum_<isc::driver::backend_type>
("backend_type")
.value("OPENCL", isc::driver::OPENCL)
#ifdef ISAAC_WITH_CUDA
.value("CUDA", isc::driver::CUDA)
#endif
;
bp::enum_<isc::driver::device_type>
("device_type")
.value("DEVICE_TYPE_GPU", isc::driver::DEVICE_TYPE_GPU)
.value("DEVICE_TYPE_CPU", isc::driver::DEVICE_TYPE_CPU)
;
bp::class_<isc::driver::Platform>("platform", bp::no_init)
.def("get_devices", &detail::get_devices)
.add_property("name",&isc::driver::Platform::name)
;
bp::enum_<isaac::driver::Device::Vendor>
("vendor")
.value("AMD", isc::driver::Device::Vendor::AMD)
.value("INTEL", isc::driver::Device::Vendor::INTEL)
.value("NVIDIA", isc::driver::Device::Vendor::NVIDIA)
.value("UNKNOWN", isc::driver::Device::Vendor::UNKNOWN)
;
bp::class_<isc::driver::Device>("device", bp::no_init)
.add_property("clock_rate", &isc::driver::Device::clock_rate)
.add_property("name", &isc::driver::Device::name)
.add_property("type", &isc::driver::Device::type)
.add_property("platform", &isc::driver::Device::platform)
.add_property("vendor", &isc::driver::Device::vendor)
.add_property("nv_compute_capability", &detail::nv_compute_capability)
;
bp::class_<isc::driver::Context, boost::noncopyable>("context", bp::no_init)
.def("__init__", bp::make_constructor(&detail::make_context))
.add_property("queues", &detail::get_queues)
.add_property("backend", &isc::driver::Context::backend)
;
bp::class_<isc::driver::CommandQueue>("command_queue", bp::init<isc::driver::Context const &, isc::driver::Device const &>())
.def("synchronize", &isc::driver::CommandQueue::synchronize)
.add_property("models", bp::make_function(&isc::database::get, bp::return_internal_reference<>()))
.add_property("device", bp::make_function(&isc::driver::CommandQueue::device, bp::return_internal_reference<>()))
;
bp::class_<isc::driver::Event>("event", bp::init<isc::driver::backend_type>())
.add_property("elapsed_time", &isc::driver::Event::elapsed_time)
;
bp::def("device_type_to_string", &detail::to_string);
bp::def("get_platforms", &detail::get_platforms);
bp::def("enqueue", &detail::enqueue, (bp::arg("expression"), bp::arg("queue_id") = 0, bp::arg("dependencies")=bp::list(), bp::arg("tune") = false, bp::arg("label")=-1, bp::arg("program_name")="", bp::arg("recompile") = false));
bp::class_<state_type>("state_type")
.def_readwrite("queue_properties",&isc::driver::backend::queue_properties)
;
bp::scope().attr("state") = bp::object(bp::ptr(&state));
bp::scope().attr("CL_QUEUE_PROFILING_ENABLE") = CL_QUEUE_PROFILING_ENABLE;
bp::scope().attr("CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE") = CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE;
}

6
python/src/bind/driver.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef ISAAC_PYTHON_DRIVER_HPP
#define ISAAC_PYTHON_DRIVER_HPP
void export_driver();
#endif

View File

@@ -0,0 +1,95 @@
#include <boost/bind.hpp>
#include <boost/python.hpp>
#include "isaac/exception/operation_not_supported.h"
#include "isaac/driver/common.h"
#include "common.hpp"
#include "exceptions.h"
namespace wrap
{
//Code taken from https://mail.python.org/pipermail/cplusplus-sig/2006-May/010347.html
template< typename CPP_ExceptionType
, typename X1 = bp::detail::not_specified
, typename X2 = bp::detail::not_specified
, typename X3 = bp::detail::not_specified
>
class exception
: public bp::class_<CPP_ExceptionType, X1, X2, X3>
{
public:
typedef bp::class_<CPP_ExceptionType, X1, X2, X3> base_type;
typedef typename base_type::wrapped_type wrapped_type;
typedef exception<CPP_ExceptionType, X1, X2, X3> self;
// Construct with the class name, with or without docstring, and default
// __init__() function
exception(char const* name, char const* doc = 0) : base_type(name, doc)
{
init();
}
// Construct with class name, no docstring, and an uncallable
// __init__ function
exception(char const* name, bp::no_init_t const& no_init_tag): base_type(name, no_init_tag)
{
init();
}
// Construct with class name, docstring, and an uncallable
// __init__ function
exception(char const* name, char const* doc, bp::no_init_t const& no_init_tag): base_type(name, doc, no_init_tag)
{
init();
}
// Construct with class name and init<> function
template <class DerivedT>
inline exception(char const* name, bp::init_base<DerivedT> const& i): base_type(name, i)
{
init();
}
// Construct with class name, docstring and init<> function
template <class DerivedT>
inline exception( char const* name
, char const* doc
, bp::init_base<DerivedT> const& i): base_type(name, doc, i)
{
init();
}
private:
static void to_python_exception(bp::object const& exn_type, wrapped_type const& exn)
{
static const bp::to_python_value<wrapped_type> convert_argument;
PyErr_SetObject(exn_type.ptr(), convert_argument(exn));
bp::throw_error_already_set();
}
void init() const
{
bp::register_exception_translator<wrapped_type>( std::bind(&to_python_exception, *this, std::placeholders::_1));
}
};
}
void export_exceptions()
{
wrap::exception<isaac::operation_not_supported_exception>("OperationNotSupported", bp::init<std::string>())
.def("__str__", &isaac::operation_not_supported_exception::what)
;
wrap::exception<isaac::driver::ocl::exception::out_of_resources>("LaunchOutOfResources")
.def("__str__", &isaac::driver::ocl::exception::out_of_resources::what)
;
wrap::exception<isaac::driver::ocl::exception::mem_object_allocation_failure>("MemObjectAllocationFailure")
.def("__str__", &isaac::driver::ocl::exception::mem_object_allocation_failure::what)
;
}

View File

@@ -0,0 +1,6 @@
#ifndef ISAAC_PYTHON_EXCEPTIONS_HPP
#define ISAAC_PYTHON_EXCEPTIONS_HPP
void export_exceptions();
#endif

71
python/src/bind/model.cpp Normal file
View File

@@ -0,0 +1,71 @@
#include "isaac/kernels/templates/axpy.h"
#include "isaac/kernels/templates/ger.h"
#include "isaac/kernels/templates/dot.h"
#include "isaac/kernels/templates/gemv.h"
#include "isaac/kernels/templates/gemm.h"
#include "isaac/model/model.h"
#include "common.hpp"
#include "model.h"
namespace tpt = isaac::templates;
namespace detail
{
bp::list input_sizes(tpt::base & temp, isc::expressions_tuple const & tree)
{
std::vector<int> tmp = temp.input_sizes(tree);
return tools::to_list(tmp.begin(), tmp.end());
}
}
void export_templates()
{
bp::object templates_module(bp::handle<>(bp::borrowed(PyImport_AddModule("isaac.templates"))));
bp::scope().attr("templates") = templates_module;
bp::scope template_scope = templates_module;
bp::enum_<tpt::fetching_policy_type>
("fetching_policy_type")
.value("FETCH_FROM_LOCAL", tpt::FETCH_FROM_LOCAL)
.value("FETCH_FROM_GLOBAL_STRIDED", tpt::FETCH_FROM_GLOBAL_STRIDED)
.value("FETCH_FROM_GLOBAL_CONTIGUOUS", tpt::FETCH_FROM_GLOBAL_CONTIGUOUS)
;
//Base
{
#define __PROP(name) .def_readonly(#name, &tpt::base::parameters_type::name)
bp::class_<tpt::base, boost::noncopyable>("base", bp::no_init)
.def("lmem_usage", &tpt::base::lmem_usage)
.def("registers_usage", &tpt::base::registers_usage)
.def("is_invalid", &tpt::base::is_invalid)
.def("input_sizes", &detail::input_sizes)
;
#undef __PROP
}
#define WRAP_BASE(name) bp::class_<tpt::base_impl<tpt::name, tpt::name::parameters_type>, bp::bases<tpt::base>, boost::noncopyable>(#name, bp::no_init);
#define WRAP_TEMPLATE(name, basename, ...) bp::class_<tpt::name, bp::bases<tpt::base_impl<tpt::basename, tpt::basename::parameters_type> > >(#name, bp::init<__VA_ARGS__>())\
.add_property("local_size_0", &tpt::name::local_size_0)\
.add_property("local_size_1", &tpt::name::local_size_1);
#define WRAP_SINGLE_TEMPLATE(name, ...) WRAP_BASE(name) WRAP_TEMPLATE(name, name, __VA_ARGS__)
//Vector AXPY
WRAP_SINGLE_TEMPLATE(axpy, uint, uint, uint, tpt::fetching_policy_type)
WRAP_SINGLE_TEMPLATE(ger, uint, uint, uint, uint, uint, tpt::fetching_policy_type)
WRAP_SINGLE_TEMPLATE(dot, uint, uint, uint, tpt::fetching_policy_type)
WRAP_BASE(gemv)
WRAP_TEMPLATE(gemv_n, gemv, uint, uint, uint, uint, uint, tpt::fetching_policy_type)
WRAP_TEMPLATE(gemv_t, gemv, uint, uint, uint, uint, uint, tpt::fetching_policy_type)
WRAP_BASE(gemm)
WRAP_TEMPLATE(gemm_nn, gemm, uint, uint, uint, uint, uint, uint, uint, uint, tpt::fetching_policy_type, tpt::fetching_policy_type, uint, uint)
WRAP_TEMPLATE(gemm_tn, gemm, uint, uint, uint, uint, uint, uint, uint, uint, tpt::fetching_policy_type, tpt::fetching_policy_type, uint, uint)
WRAP_TEMPLATE(gemm_nt, gemm, uint, uint, uint, uint, uint, uint, uint, uint, tpt::fetching_policy_type, tpt::fetching_policy_type, uint, uint)
WRAP_TEMPLATE(gemm_tt, gemm, uint, uint, uint, uint, uint, uint, uint, uint, tpt::fetching_policy_type, tpt::fetching_policy_type, uint, uint)
}

6
python/src/bind/model.h Normal file
View File

@@ -0,0 +1,6 @@
#ifndef ISAAC_PYTHON_MODEL_HPP
#define ISAAC_PYTHON_MODEL_HPP
void export_templates();
#endif