#ifndef ATIDLAS_UTILS_HPP #define ATIDLAS_UTILS_HPP #include #include "viennacl/matrix_def.hpp" #include "viennacl/vector_def.hpp" #include "viennacl/ocl/forwards.h" #include "viennacl/scheduler/forwards.h" #include "viennacl/traits/size.hpp" #include "viennacl/traits/handle.hpp" #include "atidlas/tools/to_string.hpp" #include "atidlas/forwards.h" namespace atidlas { namespace tools { //CUDA Conversion inline std::string opencl_source_to_cuda_source(std::string const & opencl_src) { std::string res = opencl_src; viennacl::tools::find_and_replace(res,"__attribute__","//__attribute__"); //Pointer viennacl::tools::find_and_replace(res, "__global float*", "float*"); viennacl::tools::find_and_replace(res, "__local float*", "float*"); viennacl::tools::find_and_replace(res, "__global double*", "double*"); viennacl::tools::find_and_replace(res, "__local double*", "double*"); //Qualifiers viennacl::tools::find_and_replace(res,"__global","__device__"); viennacl::tools::find_and_replace(res,"__kernel","__global__"); viennacl::tools::find_and_replace(res,"__constant","__constant__"); viennacl::tools::find_and_replace(res,"__local","__shared__"); //Indexing viennacl::tools::find_and_replace(res,"get_num_groups(0)","gridDim.x"); viennacl::tools::find_and_replace(res,"get_num_groups(1)","gridDim.y"); viennacl::tools::find_and_replace(res,"get_local_size(0)","blockDim.x"); viennacl::tools::find_and_replace(res,"get_local_size(1)","blockDim.y"); viennacl::tools::find_and_replace(res,"get_group_id(0)","blockIdx.x"); viennacl::tools::find_and_replace(res,"get_group_id(1)","blockIdx.y"); viennacl::tools::find_and_replace(res,"get_local_id(0)","threadIdx.x"); viennacl::tools::find_and_replace(res,"get_local_id(1)","threadIdx.y"); viennacl::tools::find_and_replace(res,"get_global_id(0)","(blockIdx.x*blockDim.x + threadIdx.x)"); viennacl::tools::find_and_replace(res,"get_global_id(1)","(blockIdx.y*blockDim.y + threadIdx.y)"); //Synchronization viennacl::tools::find_and_replace(res,"barrier(CLK_LOCAL_MEM_FENCE)","__syncthreads()"); viennacl::tools::find_and_replace(res,"barrier(CLK_GLOBAL_MEM_FENCE)","__syncthreads()"); return res; } static std::string numeric_type_to_string(viennacl::scheduler::statement_node_numeric_type const & type){ switch (type) { //case viennacl::scheduler::CHAR_TYPE: return "char"; //case viennacl::scheduler::UCHAR_TYPE: return "unsigned char"; //case viennacl::scheduler::SHORT_TYPE: return "short"; //case viennacl::scheduler::USHORT_TYPE: return "unsigned short"; case viennacl::scheduler::INT_TYPE: return "int"; case viennacl::scheduler::UINT_TYPE: return "unsigned int"; case viennacl::scheduler::LONG_TYPE: return "long"; case viennacl::scheduler::ULONG_TYPE: return "unsigned long"; case viennacl::scheduler::FLOAT_TYPE : return "float"; case viennacl::scheduler::DOUBLE_TYPE : return "double"; default : throw generator_not_supported_exception("Unsupported Scalartype"); } } template static typename Fun::result_type call_on_host_scalar(viennacl::scheduler::lhs_rhs_element element, Fun const & fun){ assert(element.type_family == viennacl::scheduler::SCALAR_TYPE_FAMILY && bool("Must be called on a host scalar")); switch (element.numeric_type) { //case viennacl::scheduler::CHAR_TYPE: return fun(element.host_char); //case viennacl::scheduler::UCHAR_TYPE: return fun(element.host_uchar); //case viennacl::scheduler::SHORT_TYPE: return fun(element.host_short); //case viennacl::scheduler::USHORT_TYPE: return fun(element.host_ushort); case viennacl::scheduler::INT_TYPE: return fun(element.host_int); case viennacl::scheduler::UINT_TYPE: return fun(element.host_uint); case viennacl::scheduler::LONG_TYPE: return fun(element.host_long); case viennacl::scheduler::ULONG_TYPE: return fun(element.host_ulong); case viennacl::scheduler::FLOAT_TYPE : return fun(element.host_float); case viennacl::scheduler::DOUBLE_TYPE : return fun(element.host_double); default : throw generator_not_supported_exception("Unsupported Scalartype"); } } template static typename Fun::result_type call_on_scalar(viennacl::scheduler::lhs_rhs_element element, Fun const & fun){ assert(element.type_family == viennacl::scheduler::SCALAR_TYPE_FAMILY && bool("Must be called on a scalar")); switch (element.numeric_type) { //case viennacl::scheduler::CHAR_TYPE: return fun(*element.scalar_char); //case viennacl::scheduler::UCHAR_TYPE: return fun(*element.scalar_uchar); //case viennacl::scheduler::SHORT_TYPE: return fun(*element.scalar_short); //case viennacl::scheduler::USHORT_TYPE: return fun(*element.scalar_ushort); case viennacl::scheduler::INT_TYPE: return fun(*element.scalar_int); case viennacl::scheduler::UINT_TYPE: return fun(*element.scalar_uint); case viennacl::scheduler::LONG_TYPE: return fun(*element.scalar_long); case viennacl::scheduler::ULONG_TYPE: return fun(*element.scalar_ulong); case viennacl::scheduler::FLOAT_TYPE : return fun(*element.scalar_float); case viennacl::scheduler::DOUBLE_TYPE : return fun(*element.scalar_double); default : throw generator_not_supported_exception("Unsupported Scalartype"); } } template static typename Fun::result_type call_on_vector(viennacl::scheduler::lhs_rhs_element element, Fun const & fun){ assert(element.type_family == viennacl::scheduler::VECTOR_TYPE_FAMILY && bool("Must be called on a vector")); switch (element.numeric_type) { //case viennacl::scheduler::CHAR_TYPE: return fun(*element.vector_char); //case viennacl::scheduler::UCHAR_TYPE: return fun(*element.vector_uchar); //case viennacl::scheduler::SHORT_TYPE: return fun(*element.vector_short); //case viennacl::scheduler::USHORT_TYPE: return fun(*element.vector_ushort); case viennacl::scheduler::INT_TYPE: return fun(*element.vector_int); case viennacl::scheduler::UINT_TYPE: return fun(*element.vector_uint); case viennacl::scheduler::LONG_TYPE: return fun(*element.vector_long); case viennacl::scheduler::ULONG_TYPE: return fun(*element.vector_ulong); case viennacl::scheduler::FLOAT_TYPE : return fun(*element.vector_float); case viennacl::scheduler::DOUBLE_TYPE : return fun(*element.vector_double); default : throw generator_not_supported_exception("Unsupported Scalartype"); } } template static typename Fun::result_type call_on_implicit_vector(viennacl::scheduler::lhs_rhs_element element, Fun const & fun){ assert(element.type_family == viennacl::scheduler::VECTOR_TYPE_FAMILY && bool("Must be called on a implicit_vector")); assert(element.subtype == viennacl::scheduler::IMPLICIT_VECTOR_TYPE && bool("Must be called on a implicit_vector")); switch (element.numeric_type) { //case viennacl::scheduler::CHAR_TYPE: return fun(*element.implicit_vector_char); //case viennacl::scheduler::UCHAR_TYPE: return fun(*element.implicit_vector_uchar); //case viennacl::scheduler::SHORT_TYPE: return fun(*element.implicit_vector_short); //case viennacl::scheduler::USHORT_TYPE: return fun(*element.implicit_vector_ushort); case viennacl::scheduler::INT_TYPE: return fun(*element.implicit_vector_int); case viennacl::scheduler::UINT_TYPE: return fun(*element.implicit_vector_uint); case viennacl::scheduler::LONG_TYPE: return fun(*element.implicit_vector_long); case viennacl::scheduler::ULONG_TYPE: return fun(*element.implicit_vector_ulong); case viennacl::scheduler::FLOAT_TYPE : return fun(*element.implicit_vector_float); case viennacl::scheduler::DOUBLE_TYPE : return fun(*element.implicit_vector_double); default : throw generator_not_supported_exception("Unsupported Scalartype"); } } template static typename Fun::result_type call_on_matrix(viennacl::scheduler::lhs_rhs_element element, Fun const & fun){ assert(element.type_family == viennacl::scheduler::MATRIX_TYPE_FAMILY && bool("Must be called on a matrix")); switch (element.numeric_type) { //case viennacl::scheduler::CHAR_TYPE: return fun(*element.matrix_char); //case viennacl::scheduler::UCHAR_TYPE: return fun(*element.matrix_uchar); //case viennacl::scheduler::SHORT_TYPE: return fun(*element.matrix_short); //case viennacl::scheduler::USHORT_TYPE: return fun(*element.matrix_ushort); case viennacl::scheduler::INT_TYPE: return fun(*element.matrix_int); case viennacl::scheduler::UINT_TYPE: return fun(*element.matrix_uint); case viennacl::scheduler::LONG_TYPE: return fun(*element.matrix_long); case viennacl::scheduler::ULONG_TYPE: return fun(*element.matrix_ulong); case viennacl::scheduler::FLOAT_TYPE : return fun(*element.matrix_float); case viennacl::scheduler::DOUBLE_TYPE : return fun(*element.matrix_double); default : throw generator_not_supported_exception("Unsupported Scalartype"); } } template static typename Fun::result_type call_on_implicit_matrix(viennacl::scheduler::lhs_rhs_element element, Fun const & fun){ assert(element.subtype == viennacl::scheduler::IMPLICIT_MATRIX_TYPE && bool("Must be called on a implicit matrix")); switch (element.numeric_type) { //case viennacl::scheduler::CHAR_TYPE: return fun(*element.implicit_matrix_char); //case viennacl::scheduler::UCHAR_TYPE: return fun(*element.implicit_matrix_uchar); //case viennacl::scheduler::SHORT_TYPE: return fun(*element.implicit_matrix_short); //case viennacl::scheduler::USHORT_TYPE: return fun(*element.implicit_matrix_ushort); case viennacl::scheduler::INT_TYPE: return fun(*element.implicit_matrix_int); case viennacl::scheduler::UINT_TYPE: return fun(*element.implicit_matrix_uint); case viennacl::scheduler::LONG_TYPE: return fun(*element.implicit_matrix_long); case viennacl::scheduler::ULONG_TYPE: return fun(*element.implicit_matrix_ulong); case viennacl::scheduler::FLOAT_TYPE : return fun(*element.implicit_matrix_float); case viennacl::scheduler::DOUBLE_TYPE : return fun(*element.implicit_matrix_double); default : throw generator_not_supported_exception("Unsupported Scalartype"); } } template static typename Fun::result_type call_on_element(viennacl::scheduler::lhs_rhs_element const & element, Fun const & fun){ switch (element.type_family) { case viennacl::scheduler::SCALAR_TYPE_FAMILY: if (element.subtype == viennacl::scheduler::HOST_SCALAR_TYPE) return call_on_host_scalar(element, fun); else return call_on_scalar(element, fun); case viennacl::scheduler::VECTOR_TYPE_FAMILY : if (element.subtype == viennacl::scheduler::IMPLICIT_VECTOR_TYPE) return call_on_implicit_vector(element, fun); else return call_on_vector(element, fun); case viennacl::scheduler::MATRIX_TYPE_FAMILY: if (element.subtype == viennacl::scheduler::IMPLICIT_MATRIX_TYPE) return call_on_implicit_matrix(element, fun); else return call_on_matrix(element,fun); default: throw generator_not_supported_exception("Unsupported datastructure type : Not among {Scalar, Vector, Matrix}"); } } struct scalartype_size_fun { typedef atidlas_int_t result_type; result_type operator()(float const &) const { return sizeof(float); } result_type operator()(double const &) const { return sizeof(double); } template result_type operator()(T const &) const { return sizeof(typename viennacl::result_of::cpu_value_type::type); } }; struct internal_size_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::internal_size(t); } }; struct size_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::size(t); } }; struct start_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::start(t); } }; struct stride_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::stride(t); } }; struct start1_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::start1(t); } }; struct start2_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::start2(t); } }; struct leading_stride_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::stride1(t); } }; struct leading_start_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::start1(t); } }; struct stride1_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::stride1(t); } }; struct stride2_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::stride2(t); } }; struct handle_fun { typedef cl_mem result_type; template result_type operator()(T const &t) const { return viennacl::traits::opencl_handle(t); } }; struct internal_size1_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::internal_size1(t); } }; struct internal_size2_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::internal_size2(t); } }; struct size1_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::size1(t); } }; struct size2_fun { typedef atidlas_int_t result_type; template result_type operator()(T const &t) const { return viennacl::traits::size2(t); } }; template struct is_same_type { enum { value = 0 }; }; template struct is_same_type { enum { value = 1 }; }; inline bool is_reduction(viennacl::scheduler::statement_node const & node) { return node.op.type_family==viennacl::scheduler::OPERATION_VECTOR_REDUCTION_TYPE_FAMILY || node.op.type_family==viennacl::scheduler::OPERATION_COLUMNS_REDUCTION_TYPE_FAMILY || node.op.type_family==viennacl::scheduler::OPERATION_ROWS_REDUCTION_TYPE_FAMILY || node.op.type==viennacl::scheduler::OPERATION_BINARY_INNER_PROD_TYPE || node.op.type==viennacl::scheduler::OPERATION_BINARY_MAT_VEC_PROD_TYPE; } inline bool is_index_reduction(viennacl::scheduler::op_element const & op) { return op.type==viennacl::scheduler::OPERATION_BINARY_ELEMENT_ARGFMAX_TYPE || op.type==viennacl::scheduler::OPERATION_BINARY_ELEMENT_ARGMAX_TYPE || op.type==viennacl::scheduler::OPERATION_BINARY_ELEMENT_ARGFMIN_TYPE || op.type==viennacl::scheduler::OPERATION_BINARY_ELEMENT_ARGMIN_TYPE; } template struct type_to_string; template<> struct type_to_string { static const char * value() { return "unsigned char"; } }; template<> struct type_to_string { static const char * value() { return "char"; } }; template<> struct type_to_string { static const char * value() { return "unsigned short"; } }; template<> struct type_to_string { static const char * value() { return "short"; } }; template<> struct type_to_string { static const char * value() { return "unsigned int"; } }; template<> struct type_to_string { static const char * value() { return "int"; } }; template<> struct type_to_string { static const char * value() { return "unsigned long"; } }; template<> struct type_to_string { static const char * value() { return "long"; } }; template<> struct type_to_string { static const char * value() { return "float"; } }; template<> struct type_to_string { static const char * value() { return "double"; } }; template struct first_letter_of_type; template<> struct first_letter_of_type { static char value() { return 'c'; } }; template<> struct first_letter_of_type { static char value() { return 'd'; } }; template<> struct first_letter_of_type { static char value() { return 's'; } }; template<> struct first_letter_of_type { static char value() { return 't'; } }; template<> struct first_letter_of_type { static char value() { return 'i'; } }; template<> struct first_letter_of_type { static char value() { return 'j'; } }; template<> struct first_letter_of_type { static char value() { return 'l'; } }; template<> struct first_letter_of_type { static char value() { return 'm'; } }; template<> struct first_letter_of_type { static char value() { return 'f'; } }; template<> struct first_letter_of_type { static char value() { return 'd'; } }; class kernel_generation_stream : public std::ostream { class kgenstream : public std::stringbuf { public: kgenstream(std::ostringstream& oss,unsigned int const & tab_count) : oss_(oss), tab_count_(tab_count){ } int sync() { for (unsigned int i=0; i(st.array()[idx].lhs); return const_cast(st.array()[idx].rhs); } inline unsigned int size_of(viennacl::scheduler::statement_node_numeric_type type) { using namespace viennacl::scheduler; switch (type) { case UCHAR_TYPE: case CHAR_TYPE: return 1; case USHORT_TYPE: case SHORT_TYPE: case HALF_TYPE: return 2; case UINT_TYPE: case INT_TYPE: case FLOAT_TYPE: return 4; case ULONG_TYPE: case LONG_TYPE: case DOUBLE_TYPE: return 8; default: throw generator_not_supported_exception("Unsupported scalartype"); } } inline std::string append_width(std::string const & str, unsigned int width) { if (width==1) return str; return str + tools::to_string(width); } template class create_map { typedef typename MapT::key_type T; typedef typename MapT::mapped_type U; public: create_map(const T& key, const U& val) { map_.insert(std::make_pair(key,val)); } create_map& operator()(const T& key, const U& val) { map_.insert(std::make_pair(key,val)); return *this; } operator MapT() { return map_; } private: MapT map_; }; typedef create_map > create_process_accessors; typedef create_map > create_evaluate_accessors; } } #endif