diff --git a/python/pyisaac/src/_isaac.cpp b/python/pyisaac/src/_isaac.cpp index 72bfc8fc8..95951e9ed 100644 --- a/python/pyisaac/src/_isaac.cpp +++ b/python/pyisaac/src/_isaac.cpp @@ -1,687 +1,22 @@ -#include -#include - #include -#include -#include #include -#include +#include "driver.h" +#include "core.h" +#include "model.h" -#include "isaac/array.h" - -#include "isaac/backend/templates/vaxpy.h" -#include "isaac/backend/templates/maxpy.h" -#include "isaac/backend/templates/reduction.h" -#include "isaac/backend/templates/mreduction.h" -#include "isaac/backend/templates/mproduct.h" - -#include "isaac/model/model.h" - -#define MAP_ENUM(v, ns) .value(#v, ns::v) namespace bp = boost::python; -namespace atd = isaac; namespace np = boost::numpy; -namespace detail -{ - -atd::numeric_type to_atd_dtype(np::dtype const & T) -{ - if(T==np::detail::get_int_dtype<8, false>()) return atd::CHAR_TYPE; - else if(T==np::detail::get_int_dtype<8, true>()) return atd::UCHAR_TYPE; - else if(T==np::detail::get_int_dtype<16, false>()) return atd::SHORT_TYPE; - else if(T==np::detail::get_int_dtype<16, true>()) return atd::USHORT_TYPE; - else if(T==np::detail::get_int_dtype<32, false>()) return atd::INT_TYPE; - else if(T==np::detail::get_int_dtype<32, true>()) return atd::UINT_TYPE; - else if(T==np::detail::get_int_dtype<64, false>()) return atd::LONG_TYPE; - else if(T==np::detail::get_int_dtype<64, true>()) return atd::ULONG_TYPE; -// else if(T==np::detail::get_float_dtype<16>()) return atd::HALF_TYPE; - else if(T==np::detail::get_float_dtype<32>()) return atd::FLOAT_TYPE; - else if(T==np::detail::get_float_dtype<64>()) return atd::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(atd::numeric_type const & T) throw() -{ - if(T==atd::CHAR_TYPE) return np::detail::get_int_dtype<8, false>(); - else if(T==atd::UCHAR_TYPE) return np::detail::get_int_dtype<8, true>(); - else if(T==atd::SHORT_TYPE) return np::detail::get_int_dtype<16, false>(); - else if(T==atd::USHORT_TYPE) return np::detail::get_int_dtype<16, true>(); - else if(T==atd::INT_TYPE) return np::detail::get_int_dtype<32, false>(); - else if(T==atd::UINT_TYPE) return np::detail::get_int_dtype<32, true>(); - else if(T==atd::LONG_TYPE) return np::detail::get_int_dtype<64, false>(); - else if(T==atd::ULONG_TYPE) return np::detail::get_int_dtype<64, true>(); -// else if(T==atd::HALF_TYPE) return np::detail::get_float_dtype<16>(); - else if(T==atd::FLOAT_TYPE) return np::detail::get_float_dtype<32>(); - else if(T==atd::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(atd::array const & x) -{ - return bp::make_tuple(x.shape()[0], x.shape()[1]); -} - -//void set_shape(atd::array & x, bp::tuple const & t) -//{ -// unsigned int len = bp::len(t); -// atd::int_t size1 = bp::extract(t[0]); -// atd::int_t size2 = len<2?1:bp::extract(t[1]); -// x.reshape(size1, size2); -//} - -//boost::python::dict create_queues(atd::cl_ext::queues_t queues) -//{ -// boost::python::dict dictionary; -// for (atd::cl_ext::queues_t::iterator it = queues.begin(); it != queues.end(); ++it) { -// bp::list list; -// for (atd::cl_ext::queues_t::mapped_type::iterator itt = it->second.begin(); itt != it->second.end(); ++itt) -// list.append(*itt); -// dictionary[it->first] = list; -// } -// return dictionary; -//} - -template -struct datatype : public atd::value_scalar -{ - datatype(T t) : atd::value_scalar(t){ } - -}; - -template -unsigned int size(datatype const & dt) -{ return atd::size_of(dt.dtype()) ; } - -#define INSTANTIATE(name, clname) \ - struct name : public detail::datatype { name(clname value) : detail::datatype(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 - -} - - - -void export_core() -{ - -#define INSTANTIATE(name, clname) \ - bp::class_, bp::bases >(#name, bp::init());\ - bp::class_ > >(#name, bp::init())\ - .add_property("size", &detail::size)\ - ; - - - 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_("operations") - MAP_ENUM(VECTOR_AXPY_TYPE, atd) - MAP_ENUM(MATRIX_AXPY_TYPE, atd) - MAP_ENUM(REDUCTION_TYPE, atd) - MAP_ENUM(ROW_WISE_REDUCTION_TYPE, atd) - MAP_ENUM(COL_WISE_REDUCTION_TYPE, atd) - MAP_ENUM(VECTOR_AXPY_TYPE, atd) - MAP_ENUM(VECTOR_AXPY_TYPE, atd) - MAP_ENUM(VECTOR_AXPY_TYPE, atd) - MAP_ENUM(VECTOR_AXPY_TYPE, atd) - ; -} - - -namespace detail -{ - template - 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 - std::vector to_vector(bp::list const & list) - { - std::size_t len = bp::len(list); - std::vector res; res.reserve(len); - for(std::size_t i = 0 ; i < len ; ++i) - res.push_back(boost::python::extract(list[i])); - return res; - } - - bp::list nv_compute_capability(atd::driver::Device const & device) - { - bp::list res; - std::pair cc = device.nv_compute_capability(); - res.append(cc.first); - res.append(cc.second); - return res; - } - - bp::list get_platforms() - { - std::vector platforms(atd::driver::Platform::get()); - return to_list(platforms.begin(), platforms.end()); - } - - bp::list get_devices(atd::driver::Platform const & platform) - { - std::vector devices(platform.devices()); - return to_list(devices.begin(), devices.end()); - } - - atd::numeric_type extract_dtype(bp::object const & odtype) - { - std::string name = bp::extract(odtype.attr("__class__").attr("__name__"))(); - if(name=="class") - name = bp::extract(odtype.attr("__name__"))(); - else - name = bp::extract(odtype.attr("__class__").attr("__name__"))(); - - if(name=="int8") return atd::CHAR_TYPE; - else if(name=="uint8") return atd::UCHAR_TYPE; - else if(name=="int16") return atd::SHORT_TYPE; - else if(name=="uint16") return atd::USHORT_TYPE; - else if(name=="int32") return atd::INT_TYPE; - else if(name=="uint32") return atd::UINT_TYPE; - else if(name=="int64") return atd::LONG_TYPE; - else if(name=="uint64") return atd::ULONG_TYPE; - else if(name=="float32") return atd::FLOAT_TYPE; - else if(name=="float64") return atd::DOUBLE_TYPE; - else - { - PyErr_SetString(PyExc_TypeError, "Data type not understood"); - bp::throw_error_already_set(); - throw; - } - } - - atd::expression_type extract_template_type(bp::object const & odtype) - { - std::string name = bp::extract(odtype.attr("__class__").attr("__name__"))(); - if(name=="class") - name = bp::extract(odtype.attr("__name__"))(); - else - name = bp::extract(odtype.attr("__class__").attr("__name__"))(); - - if(name=="vaxpy") return atd::VECTOR_AXPY_TYPE; - else if(name=="maxpy") return atd::MATRIX_AXPY_TYPE; - else if(name=="reduction") return atd::REDUCTION_TYPE; - else if(name=="mreduction_rows") return atd::ROW_WISE_REDUCTION_TYPE; - else if(name=="mreduction_cols") return atd::COL_WISE_REDUCTION_TYPE; - else if(name=="mproduct_nn") return atd::MATRIX_PRODUCT_NN_TYPE; - else if(name=="mproduct_tn") return atd::MATRIX_PRODUCT_TN_TYPE; - else if(name=="mproduct_nt") return atd::MATRIX_PRODUCT_NT_TYPE; - else if(name=="mproduct_tt") return atd::MATRIX_PRODUCT_TT_TYPE; - else - { - PyErr_SetString(PyExc_TypeError, "Template type not understood"); - bp::throw_error_already_set(); - throw; - } - } - - struct model_map_indexing - { - static atd::model& get_item(atd::model_map_t& container, bp::tuple i_) - { - atd::expression_type expression = extract_template_type(i_[0]); - atd::numeric_type dtype = extract_dtype(i_[1]); - atd::model_map_t::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(atd::model_map_t& container, bp::tuple i_, atd::model const & v) - { - atd::expression_type expression = extract_template_type(i_[0]); - atd::numeric_type dtype = extract_dtype(i_[1]); - container[std::make_pair(expression, dtype)].reset(new atd::model(v)); - } - }; - - std::string to_string(atd::driver::device_type type) - { - if(type==atd::driver::DEVICE_TYPE_CPU) return "CPU"; - if(type==atd::driver::DEVICE_TYPE_GPU) return "GPU"; - if(type==atd::driver::DEVICE_TYPE_ACCELERATOR) return "ACCELERATOR"; - throw; - } - - std::shared_ptr make_context(atd::driver::Device const & dev) - { return std::shared_ptr(new atd::driver::Context(dev)); } - - bp::tuple flush(atd::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 events; - std::vector cdependencies = to_vector(dependencies); - std::shared_ptr parray(new atd::array(atd::control(expression, - atd::execution_options_type(queue_id, &events, &cdependencies), - atd::dispatcher_options_type(tune, label), - atd::compilation_options_type(program_name, force_recompile)))); - return bp::make_tuple(parray, to_list(events.begin(), events.end())); - } -} - -struct state_type{ }; -state_type state; - -void export_cl() -{ - typedef std::vector queues_t; - bp::class_("queues") - .def("__len__", &queues_t::size) - .def("__getitem__", &bp::vector_indexing_suite::get_item, bp::return_internal_reference<>()) - .def("__setitem__", &bp::vector_indexing_suite::set_item, bp::with_custodian_and_ward<1,2>()) - .def("append", &bp::vector_indexing_suite::append) - - ; - - bp::class_("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_ - ("backend_type") - .value("OPENCL", atd::driver::OPENCL) - #ifdef ISAAC_WITH_CUDA - .value("CUDA", atd::driver::CUDA) - #endif - ; - - bp::enum_ - ("device_type") - .value("DEVICE_TYPE_GPU", atd::driver::DEVICE_TYPE_GPU) - .value("DEVICE_TYPE_CPU", atd::driver::DEVICE_TYPE_CPU) - ; - - - bp::class_("platform", bp::no_init) - .def("get_devices", &detail::get_devices) - .add_property("name",&atd::driver::Platform::name) - ; - - bp::enum_ - ("vendor") - .value("AMD", atd::driver::Device::AMD) - .value("INTEL", atd::driver::Device::INTEL) - .value("NVIDIA", atd::driver::Device::NVIDIA) - .value("UNKNOWN", atd::driver::Device::UNKNOWN) - ; - - bp::class_("device", bp::no_init) - .add_property("clock_rate", &atd::driver::Device::clock_rate) - .add_property("name", &atd::driver::Device::name) - .add_property("type", &atd::driver::Device::type) - .add_property("platform", &atd::driver::Device::platform) - .add_property("vendor", &atd::driver::Device::vendor) - .add_property("nv_compute_capability", &detail::nv_compute_capability) - ; - - bp::class_("context", bp::no_init) - .def("__init__", bp::make_constructor(&detail::make_context)) - .add_property("queues", bp::make_function(static_cast & (*)(const atd::driver::Context&)>( [](const atd::driver::Context & ctx) -> std::vector & { return atd::driver::queues[ctx]; }) , bp::return_internal_reference<>())) - .add_property("backend", &atd::driver::Context::backend) - ; - - bp::class_("command_queue", bp::init()) - .def("synchronize", &atd::driver::CommandQueue::synchronize) - .add_property("models", bp::make_function(&atd::get_model_map, bp::return_internal_reference<>())) - .add_property("device", bp::make_function(&atd::driver::CommandQueue::device, bp::return_internal_reference<>())) - ; - - bp::class_("event", bp::init()) - .add_property("elapsed_time", &atd::driver::Event::elapsed_time) - ; - - bp::def("device_type_to_string", &detail::to_string); - - bp::def("get_platforms", &detail::get_platforms); - - bp::def("flush", &detail::flush, (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") - .def_readwrite("queue_properties",&atd::driver::queues.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; -} - -namespace detail -{ - std::shared_ptr - ndarray_to_atdarray(const np::ndarray& array, const atd::driver::Context& 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(); - } - - atd::numeric_type dtype = to_atd_dtype(array.get_dtype()); - atd::int_t size = (atd::int_t)array.shape(0); - atd::array* v = new atd::array(size, dtype, ctx); - - void* data = (void*)array.get_data(); - atd::copy(data, *v); - - return std::shared_ptr(v); - } - - - - std::shared_ptr create_array(bp::object const & obj, bp::object odtype, atd::driver::Context context) - { - return ndarray_to_atdarray(np::from_object(obj, to_np_dtype(extract_dtype(odtype))), context); - } - - std::shared_ptr create_empty_array(bp::object sizes, bp::object odtype, atd::driver::Context context) - { - typedef std::shared_ptr result_type; - - std::size_t len; - int size1; - int size2; - try{ - len = bp::len(sizes); - size1 = bp::extract(sizes[0])(); - size2 = bp::extract(sizes[1])(); - }catch(bp::error_already_set const &){ - PyErr_Clear(); - len = 1; - size1 = bp::extract(sizes)(); - } - - atd::numeric_type dtype = 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 atd::array(size1, dtype, context)); - return result_type(new atd::array(size1, size2, dtype, context)); - } - - std::string type_name(bp::object const & obj) - { - std::string name = bp::extract(obj.attr("__class__").attr("__name__"))(); - if(name=="class") - return bp::extract(obj.attr("__name__"))(); - else - return bp::extract(obj.attr("__class__").attr("__name__"))(); - } - - std::shared_ptr construct_scalar(bp::object obj, atd::driver::Context const & context) - { - typedef std::shared_ptr result_type; - std::string name = type_name(obj); - if(name=="int") return result_type(new atd::scalar(bp::extract(obj)(), context)); - else if(name=="float") return result_type(new atd::scalar(bp::extract(obj)(), context)); - else if(name=="long") return result_type(new atd::scalar(bp::extract(obj)(), context)); - else if(name=="int") return result_type(new atd::scalar(bp::extract(obj)(), context)); - - else if(name=="int8") return result_type(new atd::scalar(atd::CHAR_TYPE, context)); - else if(name=="uint8") return result_type(new atd::scalar(atd::UCHAR_TYPE, context)); - else if(name=="int16") return result_type(new atd::scalar(atd::SHORT_TYPE, context)); - else if(name=="uint16") return result_type(new atd::scalar(atd::USHORT_TYPE, context)); - else if(name=="int32") return result_type(new atd::scalar(atd::INT_TYPE, context)); - else if(name=="uint32") return result_type(new atd::scalar(atd::UINT_TYPE, context)); - else if(name=="int64") return result_type(new atd::scalar(atd::LONG_TYPE, context)); - else if(name=="uint64") return result_type(new atd::scalar(atd::ULONG_TYPE, context)); - else if(name=="float32") return result_type(new atd::scalar(atd::FLOAT_TYPE, context)); - else if(name=="float64") return result_type(new atd::scalar(atd::DOUBLE_TYPE, context)); - else{ - PyErr_SetString(PyExc_TypeError, "Data type not understood"); - bp::throw_error_already_set(); - throw; - } - - } -} - -void export_array() -{ -#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())\ - .def(int() OP bp::self)\ - .def(long() OP bp::self)\ - .def(double() OP bp::self)\ - .def(bp::other() OP bp::self) - -#define ADD_ARRAY_OPERATOR(OP)\ - .def(bp::self OP bp::self)\ - ADD_SCALAR_HANDLING(OP) - - bp::class_ - ("array_expression_container", bp::init()) - ; - - bp::class_("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(&atd::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())\ - .def(bp::other() OP bp::self) \ - ADD_SCALAR_HANDLING(OP) - - bp::class_ > - ( "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")=atd::driver::queues.default_context()))) - .def(bp::init()) - .add_property("dtype", &atd::array::dtype) - .add_property("context", bp::make_function(&atd::array::context, bp::return_internal_reference<>())) - .add_property("T", &atd::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_ > - ("scalar", bp::no_init) - .def("__init__", bp::make_constructor(detail::construct_scalar, bp::default_call_policies(), (bp::arg(""), bp::arg("context")=atd::driver::queues.default_context()))) - ; - - //Other numpy-like initializers - bp::def("empty", &detail::create_empty_array, (bp::arg("shape"), bp::arg("dtype") = bp::scope().attr("float32"), bp::arg("context")=atd::driver::queues.default_context())); - -//Binary -#define MAP_FUNCTION(name) \ - bp::def(#name, static_cast(&atd::name));\ - bp::def(#name, static_cast(&atd::name));\ - bp::def(#name, static_cast(&atd::name));\ - bp::def(#name, static_cast(&atd::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(&atd::name));\ - bp::def(#name, static_cast(&atd::name)); - - 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(&atd::name));\ - bp::def(#name, static_cast(&atd::name)); - - MAP_FUNCTION(sum) - MAP_FUNCTION(max) - MAP_FUNCTION(min) - MAP_FUNCTION(argmax) - MAP_FUNCTION(argmin) -#undef MAP_FUNCTION -} - -void export_scalar() -{ - bp::class_("value_scalar", bp::no_init) - .add_property("dtype", &atd::value_scalar::dtype); -} - - -namespace detail -{ - bp::list input_sizes(isaac::base & temp, atd::expressions_tuple const & tree) - { - std::vector tmp = temp.input_sizes(tree); - return detail::to_list(tmp.begin(), tmp.end()); - } - - std::shared_ptr construct_model(bp::object dtype, bp::object const & tp, atd::driver::CommandQueue & queue) - { - return std::shared_ptr(new atd::model(extract_template_type(tp), extract_dtype(dtype), (atd::base const &)bp::extract(tp), queue)); - } -} - -void export_model() -{ - - bp::class_("model", bp::no_init) - .def("__init__", bp::make_constructor(detail::construct_model)) - .def("execute", &atd::model::execute); - - bp::enum_ - ("fetching_policy_type") - .value("FETCH_FROM_LOCAL", atd::FETCH_FROM_LOCAL) - .value("FETCH_FROM_GLOBAL_STRIDED", atd::FETCH_FROM_GLOBAL_STRIDED) - .value("FETCH_FROM_GLOBAL_CONTIGUOUS", atd::FETCH_FROM_GLOBAL_CONTIGUOUS) - ; - - //Base - { - #define __PROP(name) .def_readonly(#name, &isaac::base::parameters_type::name) - bp::class_("base", bp::no_init) - .def("lmem_usage", &isaac::base::lmem_usage) - .def("registers_usage", &isaac::base::registers_usage) - .def("is_invalid", &isaac::base::is_invalid) - .def("input_sizes", &detail::input_sizes) - ; - #undef __PROP - } - - #define WRAP_BASE(name) bp::class_, bp::bases, boost::noncopyable>(#name "_base_impl", bp::no_init); - #define WRAP_TEMPLATE(name, basename, ...) bp::class_ > >(#name, bp::init<__VA_ARGS__>())\ - .add_property("local_size_0", &atd::name::local_size_0)\ - .add_property("local_size_1", &atd::name::local_size_1); - #define WRAP_SINGLE_TEMPLATE(name, ...) WRAP_BASE(name) WRAP_TEMPLATE(name, name, __VA_ARGS__) - - //Vector AXPY - WRAP_SINGLE_TEMPLATE(vaxpy, uint, uint, uint, isaac::fetching_policy_type) - WRAP_SINGLE_TEMPLATE(maxpy, uint, uint, uint, uint, uint, isaac::fetching_policy_type) - WRAP_SINGLE_TEMPLATE(reduction, uint, uint, uint, isaac::fetching_policy_type) - WRAP_BASE(mreduction) - WRAP_TEMPLATE(mreduction_rows, mreduction, uint, uint, uint, uint, uint, isaac::fetching_policy_type) - WRAP_TEMPLATE(mreduction_cols, mreduction, uint, uint, uint, uint, uint, isaac::fetching_policy_type) - WRAP_BASE(mproduct) - WRAP_TEMPLATE(mproduct_nn, mproduct, uint, uint, uint, uint, uint, uint, uint, uint, isaac::fetching_policy_type, isaac::fetching_policy_type, uint, uint) - WRAP_TEMPLATE(mproduct_tn, mproduct, uint, uint, uint, uint, uint, uint, uint, uint, isaac::fetching_policy_type, isaac::fetching_policy_type, uint, uint) - WRAP_TEMPLATE(mproduct_nt, mproduct, uint, uint, uint, uint, uint, uint, uint, uint, isaac::fetching_policy_type, isaac::fetching_policy_type, uint, uint) - WRAP_TEMPLATE(mproduct_tt, mproduct, uint, uint, uint, uint, uint, uint, uint, uint, isaac::fetching_policy_type, isaac::fetching_policy_type, uint, uint) - - -} - BOOST_PYTHON_MODULE(_isaac) { Py_Initialize(); - np::initialize(); + boost::numpy::initialize(); // specify that this module is actually a package bp::object package = bp::scope(); package.attr("__path__") = "_isaac"; - export_scalar(); export_core(); - export_cl(); + export_driver(); export_model(); - export_array(); } diff --git a/python/pyisaac/src/common.hpp b/python/pyisaac/src/common.hpp new file mode 100644 index 000000000..41d10ef8a --- /dev/null +++ b/python/pyisaac/src/common.hpp @@ -0,0 +1,131 @@ +#ifndef PYTHON_ISAAC_SRC_COMMON_HPP +#define PYTHON_ISAAC_SRC_COMMON_HPP + +#include +#include +#include + +#include "isaac/array.h" + +#define MAP_ENUM(v, ns) .value(#v, ns::v) + +namespace bp = boost::python; +namespace np = boost::numpy; +namespace atd = isaac; + +namespace detail +{ + template + 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 + std::vector to_vector(bp::list const & list) + { + std::size_t len = bp::len(list); + std::vector res; res.reserve(len); + for(std::size_t i = 0 ; i < len ; ++i) + res.push_back(boost::python::extract(list[i])); + return res; + } + + inline atd::numeric_type extract_dtype(bp::object const & odtype) + { + std::string name = bp::extract(odtype.attr("__class__").attr("__name__"))(); + if(name=="class") + name = bp::extract(odtype.attr("__name__"))(); + else + name = bp::extract(odtype.attr("__class__").attr("__name__"))(); + + if(name=="int8") return atd::CHAR_TYPE; + else if(name=="uint8") return atd::UCHAR_TYPE; + else if(name=="int16") return atd::SHORT_TYPE; + else if(name=="uint16") return atd::USHORT_TYPE; + else if(name=="int32") return atd::INT_TYPE; + else if(name=="uint32") return atd::UINT_TYPE; + else if(name=="int64") return atd::LONG_TYPE; + else if(name=="uint64") return atd::ULONG_TYPE; + else if(name=="float32") return atd::FLOAT_TYPE; + else if(name=="float64") return atd::DOUBLE_TYPE; + else + { + PyErr_SetString(PyExc_TypeError, "Data type not understood"); + bp::throw_error_already_set(); + throw; + } + } + + inline atd::expression_type extract_template_type(bp::object const & odtype) + { + std::string name = bp::extract(odtype.attr("__class__").attr("__name__"))(); + if(name=="class") + name = bp::extract(odtype.attr("__name__"))(); + else + name = bp::extract(odtype.attr("__class__").attr("__name__"))(); + + if(name=="vaxpy") return atd::VECTOR_AXPY_TYPE; + else if(name=="maxpy") return atd::MATRIX_AXPY_TYPE; + else if(name=="reduction") return atd::REDUCTION_TYPE; + else if(name=="mreduction_rows") return atd::ROW_WISE_REDUCTION_TYPE; + else if(name=="mreduction_cols") return atd::COL_WISE_REDUCTION_TYPE; + else if(name=="mproduct_nn") return atd::MATRIX_PRODUCT_NN_TYPE; + else if(name=="mproduct_tn") return atd::MATRIX_PRODUCT_TN_TYPE; + else if(name=="mproduct_nt") return atd::MATRIX_PRODUCT_NT_TYPE; + else if(name=="mproduct_tt") return atd::MATRIX_PRODUCT_TT_TYPE; + else + { + PyErr_SetString(PyExc_TypeError, "Template type not understood"); + bp::throw_error_already_set(); + throw; + } + } + + inline atd::numeric_type to_atd_dtype(np::dtype const & T) + { + if(T==np::detail::get_int_dtype<8, false>()) return atd::CHAR_TYPE; + else if(T==np::detail::get_int_dtype<8, true>()) return atd::UCHAR_TYPE; + else if(T==np::detail::get_int_dtype<16, false>()) return atd::SHORT_TYPE; + else if(T==np::detail::get_int_dtype<16, true>()) return atd::USHORT_TYPE; + else if(T==np::detail::get_int_dtype<32, false>()) return atd::INT_TYPE; + else if(T==np::detail::get_int_dtype<32, true>()) return atd::UINT_TYPE; + else if(T==np::detail::get_int_dtype<64, false>()) return atd::LONG_TYPE; + else if(T==np::detail::get_int_dtype<64, true>()) return atd::ULONG_TYPE; + // else if(T==np::detail::get_float_dtype<16>()) return atd::HALF_TYPE; + else if(T==np::detail::get_float_dtype<32>()) return atd::FLOAT_TYPE; + else if(T==np::detail::get_float_dtype<64>()) return atd::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 + } + } + + inline np::dtype to_np_dtype(atd::numeric_type const & T) throw() + { + if(T==atd::CHAR_TYPE) return np::detail::get_int_dtype<8, false>(); + else if(T==atd::UCHAR_TYPE) return np::detail::get_int_dtype<8, true>(); + else if(T==atd::SHORT_TYPE) return np::detail::get_int_dtype<16, false>(); + else if(T==atd::USHORT_TYPE) return np::detail::get_int_dtype<16, true>(); + else if(T==atd::INT_TYPE) return np::detail::get_int_dtype<32, false>(); + else if(T==atd::UINT_TYPE) return np::detail::get_int_dtype<32, true>(); + else if(T==atd::LONG_TYPE) return np::detail::get_int_dtype<64, false>(); + else if(T==atd::ULONG_TYPE) return np::detail::get_int_dtype<64, true>(); + // else if(T==atd::HALF_TYPE) return np::detail::get_float_dtype<16>(); + else if(T==atd::FLOAT_TYPE) return np::detail::get_float_dtype<32>(); + else if(T==atd::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 + } + } + + +} + +#endif diff --git a/python/pyisaac/src/core.cpp b/python/pyisaac/src/core.cpp new file mode 100644 index 000000000..510deae13 --- /dev/null +++ b/python/pyisaac/src/core.cpp @@ -0,0 +1,293 @@ +#include "core.h" +#include "common.hpp" + +std::shared_ptr +ndarray_to_atdarray(const np::ndarray& array, const atd::driver::Context& 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(); + } + + atd::numeric_type dtype = detail::to_atd_dtype(array.get_dtype()); + atd::int_t size = (atd::int_t)array.shape(0); + atd::array* v = new atd::array(size, dtype, ctx); + + void* data = (void*)array.get_data(); + atd::copy(data, *v); + + return std::shared_ptr(v); +} + + + +std::shared_ptr create_array(bp::object const & obj, bp::object odtype, atd::driver::Context context) +{ + return ndarray_to_atdarray(np::from_object(obj, detail::to_np_dtype(detail::extract_dtype(odtype))), context); +} + +std::shared_ptr create_empty_array(bp::object sizes, bp::object odtype, atd::driver::Context context) +{ + typedef std::shared_ptr result_type; + + std::size_t len; + int size1; + int size2; + try{ + len = bp::len(sizes); + size1 = bp::extract(sizes[0])(); + size2 = bp::extract(sizes[1])(); + }catch(bp::error_already_set const &){ + PyErr_Clear(); + len = 1; + size1 = bp::extract(sizes)(); + } + + atd::numeric_type dtype = detail::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 atd::array(size1, dtype, context)); + return result_type(new atd::array(size1, size2, dtype, context)); +} + +std::string type_name(bp::object const & obj) +{ + std::string name = bp::extract(obj.attr("__class__").attr("__name__"))(); + if(name=="class") + return bp::extract(obj.attr("__name__"))(); + else + return bp::extract(obj.attr("__class__").attr("__name__"))(); +} + +std::shared_ptr construct_scalar(bp::object obj, atd::driver::Context const & context) +{ + typedef std::shared_ptr result_type; + std::string name = type_name(obj); + if(name=="int") return result_type(new atd::scalar(bp::extract(obj)(), context)); + else if(name=="float") return result_type(new atd::scalar(bp::extract(obj)(), context)); + else if(name=="long") return result_type(new atd::scalar(bp::extract(obj)(), context)); + else if(name=="int") return result_type(new atd::scalar(bp::extract(obj)(), context)); + + else if(name=="int8") return result_type(new atd::scalar(atd::CHAR_TYPE, context)); + else if(name=="uint8") return result_type(new atd::scalar(atd::UCHAR_TYPE, context)); + else if(name=="int16") return result_type(new atd::scalar(atd::SHORT_TYPE, context)); + else if(name=="uint16") return result_type(new atd::scalar(atd::USHORT_TYPE, context)); + else if(name=="int32") return result_type(new atd::scalar(atd::INT_TYPE, context)); + else if(name=="uint32") return result_type(new atd::scalar(atd::UINT_TYPE, context)); + else if(name=="int64") return result_type(new atd::scalar(atd::LONG_TYPE, context)); + else if(name=="uint64") return result_type(new atd::scalar(atd::ULONG_TYPE, context)); + else if(name=="float32") return result_type(new atd::scalar(atd::FLOAT_TYPE, context)); + else if(name=="float64") return result_type(new atd::scalar(atd::DOUBLE_TYPE, context)); + else{ + PyErr_SetString(PyExc_TypeError, "Data type not understood"); + bp::throw_error_already_set(); + throw; + } + +} + +bp::tuple get_shape(atd::array const & x) +{ + return bp::make_tuple(x.shape()[0], x.shape()[1]); +} + +template +struct datatype : public atd::value_scalar +{ + datatype(T t) : atd::value_scalar(t){ } + +}; + +template +unsigned int size(datatype const & dt) +{ return atd::size_of(dt.dtype()) ; } + +#define INSTANTIATE(name, clname) \ + struct name : public datatype { name(clname value) : datatype(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 + +void export_core() +{ + /*------------------- + * TYPES + *------------------*/ + #define INSTANTIATE(name, clname) \ + bp::class_, bp::bases >(#name, bp::init());\ + bp::class_ > >(#name, bp::init())\ + .add_property("size", &size)\ + ; + + + 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_("operations") + MAP_ENUM(VECTOR_AXPY_TYPE, atd) + MAP_ENUM(MATRIX_AXPY_TYPE, atd) + MAP_ENUM(REDUCTION_TYPE, atd) + MAP_ENUM(ROW_WISE_REDUCTION_TYPE, atd) + MAP_ENUM(COL_WISE_REDUCTION_TYPE, atd) + MAP_ENUM(VECTOR_AXPY_TYPE, atd) + MAP_ENUM(VECTOR_AXPY_TYPE, atd) + MAP_ENUM(VECTOR_AXPY_TYPE, atd) + MAP_ENUM(VECTOR_AXPY_TYPE, atd) + ; + + /*------------------- + * ARRAY + *------------------*/ + #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())\ + .def(int() OP bp::self)\ + .def(long() OP bp::self)\ + .def(double() OP bp::self)\ + .def(bp::other() OP bp::self) + + #define ADD_ARRAY_OPERATOR(OP)\ + .def(bp::self OP bp::self)\ + ADD_SCALAR_HANDLING(OP) + + bp::class_ + ("array_expression_container", bp::init()) + ; + + bp::class_("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(&atd::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())\ + .def(bp::other() OP bp::self) \ + ADD_SCALAR_HANDLING(OP) + + bp::class_ > + ( "array", bp::no_init) + .def("__init__", bp::make_constructor(create_array, bp::default_call_policies(), (bp::arg("obj"), bp::arg("dtype") = bp::scope().attr("float32"), bp::arg("context")=atd::driver::queues.default_context()))) + .def(bp::init()) + .add_property("dtype", &atd::array::dtype) + .add_property("context", bp::make_function(&atd::array::context, bp::return_internal_reference<>())) + .add_property("T", &atd::array::T) + .add_property("shape", &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_ > + ("scalar", bp::no_init) + .def("__init__", bp::make_constructor(construct_scalar, bp::default_call_policies(), (bp::arg(""), bp::arg("context")=atd::driver::queues.default_context()))) + ; + + //Other numpy-like initializers + bp::def("empty", &create_empty_array, (bp::arg("shape"), bp::arg("dtype") = bp::scope().attr("float32"), bp::arg("context")=atd::driver::queues.default_context())); + + //Binary + #define MAP_FUNCTION(name) \ + bp::def(#name, static_cast(&atd::name));\ + bp::def(#name, static_cast(&atd::name));\ + bp::def(#name, static_cast(&atd::name));\ + bp::def(#name, static_cast(&atd::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(&atd::name));\ + bp::def(#name, static_cast(&atd::name)); + + 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(&atd::name));\ + bp::def(#name, static_cast(&atd::name)); + + MAP_FUNCTION(sum) + MAP_FUNCTION(max) + MAP_FUNCTION(min) + MAP_FUNCTION(argmax) + MAP_FUNCTION(argmin) + #undef MAP_FUNCTION + + /*------------------- + * SCALAR + *------------------*/ + bp::class_("value_scalar", bp::no_init) + .add_property("dtype", &atd::value_scalar::dtype); + + +} diff --git a/python/pyisaac/src/core.h b/python/pyisaac/src/core.h new file mode 100644 index 000000000..e4df2f1fd --- /dev/null +++ b/python/pyisaac/src/core.h @@ -0,0 +1,6 @@ +#ifndef PYISAAC_SRC_CORE_H +#define PYISAAC_SRC_CORE_H + +void export_core(); + +#endif diff --git a/python/pyisaac/src/driver.cpp b/python/pyisaac/src/driver.cpp new file mode 100644 index 000000000..58dff4f6b --- /dev/null +++ b/python/pyisaac/src/driver.cpp @@ -0,0 +1,165 @@ +#include +#include +#include + +#include "isaac/array.h" +#include "isaac/model/model.h" + +#include "common.hpp" +#include "driver.h" + + +bp::list nv_compute_capability(atd::driver::Device const & device) +{ + bp::list res; + std::pair cc = device.nv_compute_capability(); + res.append(cc.first); + res.append(cc.second); + return res; +} + +bp::list get_platforms() +{ + std::vector platforms(atd::driver::Platform::get()); + return detail::to_list(platforms.begin(), platforms.end()); +} + +bp::list get_devices(atd::driver::Platform const & platform) +{ + std::vector devices(platform.devices()); + return detail::to_list(devices.begin(), devices.end()); +} + +struct model_map_indexing +{ + static atd::model& get_item(atd::model_map_t& container, bp::tuple i_) + { + atd::expression_type expression = detail::extract_template_type(i_[0]); + atd::numeric_type dtype = detail::extract_dtype(i_[1]); + atd::model_map_t::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(atd::model_map_t& container, bp::tuple i_, atd::model const & v) + { + atd::expression_type expression = detail::extract_template_type(i_[0]); + atd::numeric_type dtype = detail::extract_dtype(i_[1]); + container[std::make_pair(expression, dtype)].reset(new atd::model(v)); + } +}; + +std::string to_string(atd::driver::device_type type) +{ + if(type==atd::driver::DEVICE_TYPE_CPU) return "CPU"; + if(type==atd::driver::DEVICE_TYPE_GPU) return "GPU"; + if(type==atd::driver::DEVICE_TYPE_ACCELERATOR) return "ACCELERATOR"; + throw; +} + +std::shared_ptr make_context(atd::driver::Device const & dev) +{ return std::shared_ptr(new atd::driver::Context(dev)); } + +bp::tuple flush(atd::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 events; + std::vector cdependencies = detail::to_vector(dependencies); + std::shared_ptr parray(new atd::array(atd::control(expression, + atd::execution_options_type(queue_id, &events, &cdependencies), + atd::dispatcher_options_type(tune, label), + atd::compilation_options_type(program_name, force_recompile)))); + return bp::make_tuple(parray, detail::to_list(events.begin(), events.end())); +} + + +struct state_type{ }; +state_type state; + +void export_cl() +{ + typedef std::vector queues_t; + bp::class_("queues") + .def("__len__", &queues_t::size) + .def("__getitem__", &bp::vector_indexing_suite::get_item, bp::return_internal_reference<>()) + .def("__setitem__", &bp::vector_indexing_suite::set_item, bp::with_custodian_and_ward<1,2>()) + .def("append", &bp::vector_indexing_suite::append) + + ; + + bp::class_("models") + .def("__getitem__", &model_map_indexing::get_item, bp::return_internal_reference<>()) + .def("__setitem__", &model_map_indexing::set_item, bp::with_custodian_and_ward<1,2>()) + ; + + bp::enum_ + ("backend_type") + .value("OPENCL", atd::driver::OPENCL) + #ifdef ISAAC_WITH_CUDA + .value("CUDA", atd::driver::CUDA) + #endif + ; + + bp::enum_ + ("device_type") + .value("DEVICE_TYPE_GPU", atd::driver::DEVICE_TYPE_GPU) + .value("DEVICE_TYPE_CPU", atd::driver::DEVICE_TYPE_CPU) + ; + + + bp::class_("platform", bp::no_init) + .def("get_devices", &get_devices) + .add_property("name",&atd::driver::Platform::name) + ; + + bp::enum_ + ("vendor") + .value("AMD", atd::driver::Device::AMD) + .value("INTEL", atd::driver::Device::INTEL) + .value("NVIDIA", atd::driver::Device::NVIDIA) + .value("UNKNOWN", atd::driver::Device::UNKNOWN) + ; + + bp::class_("device", bp::no_init) + .add_property("clock_rate", &atd::driver::Device::clock_rate) + .add_property("name", &atd::driver::Device::name) + .add_property("type", &atd::driver::Device::type) + .add_property("platform", &atd::driver::Device::platform) + .add_property("vendor", &atd::driver::Device::vendor) + .add_property("nv_compute_capability", &nv_compute_capability) + ; + + bp::class_("context", bp::no_init) + .def("__init__", bp::make_constructor(&make_context)) + .add_property("queues", bp::make_function(static_cast & (*)(const atd::driver::Context&)>( [](const atd::driver::Context & ctx) -> std::vector & { return atd::driver::queues[ctx]; }) , bp::return_internal_reference<>())) + .add_property("backend", &atd::driver::Context::backend) + ; + + bp::class_("command_queue", bp::init()) + .def("synchronize", &atd::driver::CommandQueue::synchronize) + .add_property("models", bp::make_function(&atd::get_model_map, bp::return_internal_reference<>())) + .add_property("device", bp::make_function(&atd::driver::CommandQueue::device, bp::return_internal_reference<>())) + ; + + bp::class_("event", bp::init()) + .add_property("elapsed_time", &atd::driver::Event::elapsed_time) + ; + + bp::def("device_type_to_string", &to_string); + + bp::def("get_platforms", &get_platforms); + + bp::def("flush", &flush, (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") + .def_readwrite("queue_properties",&atd::driver::queues.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; +} diff --git a/python/pyisaac/src/driver.h b/python/pyisaac/src/driver.h new file mode 100644 index 000000000..fbd232c16 --- /dev/null +++ b/python/pyisaac/src/driver.h @@ -0,0 +1,6 @@ +#ifndef PYISAAC_SRC_DRIVER_H +#define PYISAAC_SRC_DRIVER_H + +void export_driver(); + +#endif diff --git a/python/pyisaac/src/model.cpp b/python/pyisaac/src/model.cpp new file mode 100644 index 000000000..dadd1b294 --- /dev/null +++ b/python/pyisaac/src/model.cpp @@ -0,0 +1,66 @@ +#include "isaac/backend/templates/vaxpy.h" +#include "isaac/backend/templates/maxpy.h" +#include "isaac/backend/templates/reduction.h" +#include "isaac/backend/templates/mreduction.h" +#include "isaac/backend/templates/mproduct.h" +#include "isaac/model/model.h" + +#include "model.h" +#include "common.hpp" + +bp::list input_sizes(isaac::base & temp, atd::expressions_tuple const & tree) +{ + std::vector tmp = temp.input_sizes(tree); + return detail::to_list(tmp.begin(), tmp.end()); +} + +std::shared_ptr construct_model(bp::object dtype, bp::object const & tp, atd::driver::CommandQueue & queue) +{ + return std::shared_ptr(new atd::model(detail::extract_template_type(tp), detail::extract_dtype(dtype), (atd::base const &)bp::extract(tp), queue)); +} + +void export_model() +{ + + bp::class_("model", bp::no_init) + .def("__init__", bp::make_constructor(construct_model)) + .def("execute", &atd::model::execute); + + bp::enum_ + ("fetching_policy_type") + .value("FETCH_FROM_LOCAL", atd::FETCH_FROM_LOCAL) + .value("FETCH_FROM_GLOBAL_STRIDED", atd::FETCH_FROM_GLOBAL_STRIDED) + .value("FETCH_FROM_GLOBAL_CONTIGUOUS", atd::FETCH_FROM_GLOBAL_CONTIGUOUS) + ; + + //Base + { + #define __PROP(name) .def_readonly(#name, &isaac::base::parameters_type::name) + bp::class_("base", bp::no_init) + .def("lmem_usage", &isaac::base::lmem_usage) + .def("registers_usage", &isaac::base::registers_usage) + .def("is_invalid", &isaac::base::is_invalid) + .def("input_sizes", &input_sizes) + ; + #undef __PROP + } + + #define WRAP_BASE(name) bp::class_, bp::bases, boost::noncopyable>(#name "_base_impl", bp::no_init); + #define WRAP_TEMPLATE(name, basename, ...) bp::class_ > >(#name, bp::init<__VA_ARGS__>())\ + .add_property("local_size_0", &atd::name::local_size_0)\ + .add_property("local_size_1", &atd::name::local_size_1); + #define WRAP_SINGLE_TEMPLATE(name, ...) WRAP_BASE(name) WRAP_TEMPLATE(name, name, __VA_ARGS__) + + //Vector AXPY + WRAP_SINGLE_TEMPLATE(vaxpy, uint, uint, uint, isaac::fetching_policy_type) + WRAP_SINGLE_TEMPLATE(maxpy, uint, uint, uint, uint, uint, isaac::fetching_policy_type) + WRAP_SINGLE_TEMPLATE(reduction, uint, uint, uint, isaac::fetching_policy_type) + WRAP_BASE(mreduction) + WRAP_TEMPLATE(mreduction_rows, mreduction, uint, uint, uint, uint, uint, isaac::fetching_policy_type) + WRAP_TEMPLATE(mreduction_cols, mreduction, uint, uint, uint, uint, uint, isaac::fetching_policy_type) + WRAP_BASE(mproduct) + WRAP_TEMPLATE(mproduct_nn, mproduct, uint, uint, uint, uint, uint, uint, uint, uint, isaac::fetching_policy_type, isaac::fetching_policy_type, uint, uint) + WRAP_TEMPLATE(mproduct_tn, mproduct, uint, uint, uint, uint, uint, uint, uint, uint, isaac::fetching_policy_type, isaac::fetching_policy_type, uint, uint) + WRAP_TEMPLATE(mproduct_nt, mproduct, uint, uint, uint, uint, uint, uint, uint, uint, isaac::fetching_policy_type, isaac::fetching_policy_type, uint, uint) + WRAP_TEMPLATE(mproduct_tt, mproduct, uint, uint, uint, uint, uint, uint, uint, uint, isaac::fetching_policy_type, isaac::fetching_policy_type, uint, uint) +} diff --git a/python/pyisaac/src/model.h b/python/pyisaac/src/model.h new file mode 100644 index 000000000..a47f48482 --- /dev/null +++ b/python/pyisaac/src/model.h @@ -0,0 +1,6 @@ +#ifndef PYISAAC_SRC_MODEL_H +#define PYISAAC_SRC_MODEL_H + +void export_model(); + +#endif