Some cleaning + outer product

This commit is contained in:
Philippe Tillet
2015-01-17 10:48:02 -05:00
parent 1d70396711
commit 0068560bc6
28 changed files with 317 additions and 255 deletions

View File

@@ -197,9 +197,9 @@ array_expression norm(array_expression const &, unsigned int order = 2);
#undef ATIDLAS_DECLARE_UNARY_OPERATOR #undef ATIDLAS_DECLARE_UNARY_OPERATOR
struct array_repeat_infos struct repeat_infos
{ {
array_repeat_infos(size4 const & _sub, size4 const & _rep) : sub(_sub), rep(_rep){ } repeat_infos(size4 const & _sub, size4 const & _rep) : sub(_sub), rep(_rep){ }
size4 sub; size4 sub;
size4 rep; size4 rep;
}; };

View File

@@ -31,6 +31,7 @@ class mapped_object
{ {
private: private:
virtual void preprocess(std::string &) const; virtual void preprocess(std::string &) const;
virtual void postprocess(std::string &) const;
protected: protected:
struct MorphBase { struct MorphBase {
@@ -73,7 +74,7 @@ class binary_leaf
public: public:
binary_leaf(mapped_object::node_info info); binary_leaf(mapped_object::node_info info);
void process_recursive(kernel_generation_stream & stream, leaf_t leaf, std::multimap<std::string, std::string> const & accessors); void process_recursive(kernel_generation_stream & stream, leaf_t leaf, std::map<std::string, std::string> const & accessors);
std::string evaluate_recursive(leaf_t leaf, std::map<std::string, std::string> const & accessors); std::string evaluate_recursive(leaf_t leaf, std::map<std::string, std::string> const & accessors);
protected: protected:
mapped_object::node_info info_; mapped_object::node_info info_;
@@ -197,18 +198,18 @@ private:
char type_; char type_;
}; };
class mapped_vector_diag : public mapped_object, public binary_leaf class mapped_vdiag : public mapped_object, public binary_leaf
{ {
private: private:
void preprocess(std::string &res) const; void postprocess(std::string &res) const;
public: public:
mapped_vector_diag(std::string const & scalartype, unsigned int id, node_info info); mapped_vdiag(std::string const & scalartype, unsigned int id, node_info info);
}; };
class mapped_trans: public mapped_object, public binary_leaf class mapped_trans: public mapped_object, public binary_leaf
{ {
private: private:
void preprocess(std::string &res) const; void postprocess(std::string &res) const;
public: public:
mapped_trans(std::string const & scalartype, unsigned int id, node_info info); mapped_trans(std::string const & scalartype, unsigned int id, node_info info);
}; };
@@ -216,7 +217,7 @@ public:
class mapped_matrix_row : public mapped_object, binary_leaf class mapped_matrix_row : public mapped_object, binary_leaf
{ {
private: private:
void preprocess(std::string &res) const; void postprocess(std::string &res) const;
public: public:
mapped_matrix_row(std::string const & scalartype, unsigned int id, node_info info); mapped_matrix_row(std::string const & scalartype, unsigned int id, node_info info);
}; };
@@ -224,26 +225,35 @@ public:
class mapped_matrix_column : public mapped_object, binary_leaf class mapped_matrix_column : public mapped_object, binary_leaf
{ {
private: private:
void preprocess(std::string &res) const; void postprocess(std::string &res) const;
public: public:
mapped_matrix_column(std::string const & scalartype, unsigned int id, node_info info); mapped_matrix_column(std::string const & scalartype, unsigned int id, node_info info);
}; };
class mapped_matrix_repeat : public mapped_object, binary_leaf class mapped_repeat : public mapped_object, binary_leaf
{ {
private: private:
void preprocess(std::string &res) const; void postprocess(std::string &res) const;
public: public:
mapped_matrix_repeat(std::string const & scalartype, unsigned int id, node_info info); mapped_repeat(std::string const & scalartype, unsigned int id, node_info info);
}; };
class mapped_matrix_diag : public mapped_object, binary_leaf class mapped_matrix_diag : public mapped_object, binary_leaf
{ {
private: private:
void preprocess(std::string &res) const; void postprocess(std::string &res) const;
public: public:
mapped_matrix_diag(std::string const & scalartype, unsigned int id, node_info info); mapped_matrix_diag(std::string const & scalartype, unsigned int id, node_info info);
}; };
class mapped_outer : public mapped_object, binary_leaf
{
private:
void postprocess(std::string &res) const;
public:
mapped_outer(std::string const & scalartype, unsigned int id, node_info info);
};
} }
#endif #endif

View File

@@ -119,20 +119,20 @@ void evaluate(kernel_generation_stream & stream, leaf_t leaf, std::map<std::stri
class process_traversal : public traversal_functor class process_traversal : public traversal_functor
{ {
public: public:
process_traversal(std::multimap<std::string, std::string> const & accessors, kernel_generation_stream & stream, process_traversal(std::map<std::string, std::string> const & accessors, kernel_generation_stream & stream,
mapping_type const & mapping, std::set<std::string> & already_processed); mapping_type const & mapping, std::set<std::string> & already_processed);
void operator()(symbolic_expression const & symbolic_expression, int_t root_idx, leaf_t leaf) const; void operator()(symbolic_expression const & symbolic_expression, int_t root_idx, leaf_t leaf) const;
private: private:
std::multimap<std::string, std::string> accessors_; std::map<std::string, std::string> accessors_;
kernel_generation_stream & stream_; kernel_generation_stream & stream_;
mapping_type const & mapping_; mapping_type const & mapping_;
std::set<std::string> & already_processed_; std::set<std::string> & already_processed_;
}; };
void process(kernel_generation_stream & stream, leaf_t leaf, std::multimap<std::string, std::string> const & accessors, void process(kernel_generation_stream & stream, leaf_t leaf, std::map<std::string, std::string> const & accessors,
atidlas::symbolic_expression const & symbolic_expression, size_t root_idx, mapping_type const & mapping, std::set<std::string> & already_processed); atidlas::symbolic_expression const & symbolic_expression, size_t root_idx, mapping_type const & mapping, std::set<std::string> & already_processed);
void process(kernel_generation_stream & stream, leaf_t leaf, std::multimap<std::string, std::string> const & accessors, void process(kernel_generation_stream & stream, leaf_t leaf, std::map<std::string, std::string> const & accessors,
symbolic_expressions_container const & symbolic_expressions, std::vector<mapping_type> const & mappings); symbolic_expressions_container const & symbolic_expressions, std::vector<mapping_type> const & mappings);

View File

@@ -1,5 +1,5 @@
#ifndef ATIDLAS_TEMPLATES_TEMPLATE_BASE_ #ifndef ATIDLAS_TEMPLATES_base_
#define ATIDLAS_TEMPLATES_TEMPLATE_BASE_ #define ATIDLAS_TEMPLATES_base_
#include <list> #include <list>
@@ -44,7 +44,7 @@ static const int TEMPLATE_LOCAL_FETCH_0_MUST_BE_NL_MULTIPLE = -16;
static const int TEMPLATE_LOCAL_FETCH_1_MUST_BE_KL_MULTIPLE = -17; static const int TEMPLATE_LOCAL_FETCH_1_MUST_BE_KL_MULTIPLE = -17;
static const int TEMPLATE_LOCAL_FETCH_1_MUST_BE_ML_MULTIPLE = -18; static const int TEMPLATE_LOCAL_FETCH_1_MUST_BE_ML_MULTIPLE = -18;
class template_base class base
{ {
public: public:
struct parameters_type struct parameters_type
@@ -81,7 +81,7 @@ protected:
/** @brief Creates a vector mapping */ /** @brief Creates a vector mapping */
tools::shared_ptr<mapped_object> create(array const &) const; tools::shared_ptr<mapped_object> create(array const &) const;
/** @brief Creates a tuple mapping */ /** @brief Creates a tuple mapping */
tools::shared_ptr<mapped_object> create(array_repeat_infos const &) const; tools::shared_ptr<mapped_object> create(repeat_infos const &) const;
/** @brief Creates a mapping */ /** @brief Creates a mapping */
tools::shared_ptr<mapped_object> create(lhs_rhs_element const &) const; tools::shared_ptr<mapped_object> create(lhs_rhs_element const &) const;
public: public:
@@ -102,7 +102,7 @@ protected:
set_arguments_functor(symbolic_binder & binder, unsigned int & current_arg, cl::Kernel & kernel); set_arguments_functor(symbolic_binder & binder, unsigned int & current_arg, cl::Kernel & kernel);
void set_arguments(numeric_type dtype, values_holder const & scal) const; void set_arguments(numeric_type dtype, values_holder const & scal) const;
void set_arguments(array const & ) const; void set_arguments(array const & ) const;
void set_arguments(array_repeat_infos const & i) const; void set_arguments(repeat_infos const & i) const;
void set_arguments(lhs_rhs_element const & lhs_rhs) const; void set_arguments(lhs_rhs_element const & lhs_rhs) const;
void operator()(atidlas::symbolic_expression const & symbolic_expression, int_t root_idx, leaf_t leaf_t) const; void operator()(atidlas::symbolic_expression const & symbolic_expression, int_t root_idx, leaf_t leaf_t) const;
@@ -129,14 +129,14 @@ protected:
kernel_generation_stream & stream, std::vector<mapping_type> const & mappings, kernel_generation_stream & stream, std::vector<mapping_type> const & mappings,
size_t root_idx, leaf_t leaf); size_t root_idx, leaf_t leaf);
static std::string neutral_element(op_element const & op); static std::string neutral_element(op_element const & op);
static std::string generate_arguments(std::vector<mapping_type> const & mappings, std::multimap<std::string, std::string> const & accessors, static std::string generate_arguments(std::vector<mapping_type> const & mappings, std::map<std::string, std::string> const & accessors,
symbolic_expressions_container const & symbolic_expressions); symbolic_expressions_container const & symbolic_expressions);
static std::string generate_arguments(std::string const & data_type, std::vector<mapping_type> const & mappings, static std::string generate_arguments(std::string const & data_type, std::vector<mapping_type> const & mappings,
symbolic_expressions_container const & symbolic_expressions); symbolic_expressions_container const & symbolic_expressions);
static void fill_kernel_name(char * ptr, unsigned int label, const char * suffix); static void fill_kernel_name(char * ptr, unsigned int label, const char * suffix);
static bool is_node_trans(symbolic_expression::container_type const & array, size_t root_idx, leaf_t leaf_type); static bool is_node_trans(symbolic_expression::container_type const & array, size_t root_idx, leaf_t leaf_type);
static std::string append_simd_suffix(std::string const & str, unsigned int i); static std::string append_simd_suffix(std::string const & str, unsigned int i);
static bool is_offset_modifier(symbolic_expression_node const & node); static bool is_strided(symbolic_expression_node const & node);
static int_t vector_size(symbolic_expression_node const & node); static int_t vector_size(symbolic_expression_node const & node);
static std::pair<int_t, int_t> matrix_size(symbolic_expression_node const & node); static std::pair<int_t, int_t> matrix_size(symbolic_expression_node const & node);
static unsigned int align(unsigned int to_round, unsigned int base); static unsigned int align(unsigned int to_round, unsigned int base);
@@ -155,24 +155,24 @@ private:
virtual std::vector<std::string> generate_impl(unsigned int label, symbolic_expressions_container const & symbolic_expressions, std::vector<mapping_type> const & mapping) const = 0; virtual std::vector<std::string> generate_impl(unsigned int label, symbolic_expressions_container const & symbolic_expressions, std::vector<mapping_type> const & mapping) const = 0;
public: public:
template_base(binding_policy_t binding_policy); base(binding_policy_t binding_policy);
virtual unsigned int lmem_usage(symbolic_expressions_container const &) const; virtual unsigned int lmem_usage(symbolic_expressions_container const &) const;
virtual unsigned int registers_usage(symbolic_expressions_container const &) const; virtual unsigned int registers_usage(symbolic_expressions_container const &) const;
virtual std::vector<int_t> input_sizes(symbolic_expressions_container const & symbolic_expressions) = 0; virtual std::vector<int_t> input_sizes(symbolic_expressions_container const & symbolic_expressions) = 0;
virtual ~template_base(); virtual ~base();
std::vector<std::string> generate(unsigned int label, symbolic_expressions_container const & symbolic_expressions, cl::Device const & device); std::vector<std::string> generate(unsigned int label, symbolic_expressions_container const & symbolic_expressions, cl::Device const & device);
virtual int check_invalid(symbolic_expressions_container const & symbolic_expressions, cl::Device const & device) const = 0; virtual int check_invalid(symbolic_expressions_container const & symbolic_expressions, cl::Device const & device) const = 0;
virtual void enqueue(cl::CommandQueue & queue, virtual void enqueue(cl::CommandQueue & queue,
std::vector<cl::lazy_compiler> & programs, std::vector<cl::lazy_compiler> & programs,
unsigned int label, symbolic_expressions_container const & symbolic_expressions) = 0; unsigned int label, symbolic_expressions_container const & symbolic_expressions) = 0;
virtual tools::shared_ptr<template_base> clone() const = 0; virtual tools::shared_ptr<base> clone() const = 0;
private: private:
binding_policy_t binding_policy_; binding_policy_t binding_policy_;
}; };
template<class TemplateType, class ParametersType> template<class TemplateType, class ParametersType>
class template_base_impl : public template_base class base_impl : public base
{ {
private: private:
virtual int check_invalid_impl(cl::Device const &, symbolic_expressions_container const &) const; virtual int check_invalid_impl(cl::Device const &, symbolic_expressions_container const &) const;
@@ -180,10 +180,10 @@ protected:
bool has_misaligned_offset(symbolic_expressions_container const & symbolic_expressions); bool has_misaligned_offset(symbolic_expressions_container const & symbolic_expressions);
public: public:
typedef ParametersType parameters_type; typedef ParametersType parameters_type;
template_base_impl(parameters_type const & parameters, binding_policy_t binding_policy); base_impl(parameters_type const & parameters, binding_policy_t binding_policy);
int_t local_size_0() const; int_t local_size_0() const;
int_t local_size_1() const; int_t local_size_1() const;
tools::shared_ptr<template_base> clone() const; tools::shared_ptr<base> clone() const;
/** @brief returns whether or not the profile has undefined behavior on particular device */ /** @brief returns whether or not the profile has undefined behavior on particular device */
int check_invalid(symbolic_expressions_container const & symbolic_expressions, cl::Device const & device) const; int check_invalid(symbolic_expressions_container const & symbolic_expressions, cl::Device const & device) const;
protected: protected:

View File

@@ -2,12 +2,12 @@
#define ATIDLAS_BACKEND_TEMPLATES_MAXPY_H #define ATIDLAS_BACKEND_TEMPLATES_MAXPY_H
#include <vector> #include <vector>
#include "atidlas/backend/templates/template_base.h" #include "atidlas/backend/templates/base.h"
namespace atidlas namespace atidlas
{ {
class maxpy_parameters : public template_base::parameters_type class maxpy_parameters : public base::parameters_type
{ {
public: public:
maxpy_parameters(unsigned int _simd_width, maxpy_parameters(unsigned int _simd_width,
@@ -20,7 +20,7 @@ public:
fetching_policy_type fetching_policy; fetching_policy_type fetching_policy;
}; };
class maxpy : public template_base_impl<maxpy, maxpy_parameters> class maxpy : public base_impl<maxpy, maxpy_parameters>
{ {
private: private:
int check_invalid_impl(cl::Device const &, symbolic_expressions_container const &) const; int check_invalid_impl(cl::Device const &, symbolic_expressions_container const &) const;

View File

@@ -1,12 +1,12 @@
#ifndef ATIDLAS_BACKEND_TEMPLATES_MPRODUCT_H #ifndef ATIDLAS_BACKEND_TEMPLATES_MPRODUCT_H
#define ATIDLAS_BACKEND_TEMPLATES_MPRODUCT_H #define ATIDLAS_BACKEND_TEMPLATES_MPRODUCT_H
#include "atidlas/backend/templates/template_base.h" #include "atidlas/backend/templates/base.h"
namespace atidlas namespace atidlas
{ {
struct mproduct_parameters : public template_base::parameters_type struct mproduct_parameters : public base::parameters_type
{ {
mproduct_parameters(unsigned int simd_width mproduct_parameters(unsigned int simd_width
, int_t local_size_0, int_t KL, int_t local_size_1 , int_t local_size_0, int_t KL, int_t local_size_1
@@ -30,7 +30,7 @@ struct mproduct_parameters : public template_base::parameters_type
int_t nL; int_t nL;
}; };
class mproduct : public template_base_impl<mproduct, mproduct_parameters> class mproduct : public base_impl<mproduct, mproduct_parameters>
{ {
private: private:
unsigned int lmem_usage(symbolic_expressions_container const & symbolic_expressions) const; unsigned int lmem_usage(symbolic_expressions_container const & symbolic_expressions) const;

View File

@@ -4,12 +4,12 @@
#include <vector> #include <vector>
#include "atidlas/symbolic/expression.h" #include "atidlas/symbolic/expression.h"
#include "atidlas/backend/templates/template_base.h" #include "atidlas/backend/templates/base.h"
namespace atidlas namespace atidlas
{ {
struct mreduction_parameters : public template_base::parameters_type struct mreduction_parameters : public base::parameters_type
{ {
mreduction_parameters(unsigned int _simd_width, mreduction_parameters(unsigned int _simd_width,
unsigned int _local_size_0, unsigned int _local_size_1, unsigned int _local_size_0, unsigned int _local_size_1,
@@ -19,7 +19,7 @@ struct mreduction_parameters : public template_base::parameters_type
}; };
class mreduction : public template_base_impl<mreduction, mreduction_parameters> class mreduction : public base_impl<mreduction, mreduction_parameters>
{ {
protected: protected:
enum reduction_type enum reduction_type

View File

@@ -1,12 +1,12 @@
#ifndef ATIDLAS_BACKEND_TEMPLATES_REDUCTION_H #ifndef ATIDLAS_BACKEND_TEMPLATES_REDUCTION_H
#define ATIDLAS_BACKEND_TEMPLATES_REDUCTION_H #define ATIDLAS_BACKEND_TEMPLATES_REDUCTION_H
#include "atidlas/backend/templates/template_base.h" #include "atidlas/backend/templates/base.h"
namespace atidlas namespace atidlas
{ {
struct reduction_parameters : public template_base::parameters_type struct reduction_parameters : public base::parameters_type
{ {
reduction_parameters(unsigned int _simd_width, reduction_parameters(unsigned int _simd_width,
unsigned int _group_size, unsigned int _num_groups, unsigned int _group_size, unsigned int _num_groups,
@@ -15,7 +15,7 @@ struct reduction_parameters : public template_base::parameters_type
fetching_policy_type fetching_policy; fetching_policy_type fetching_policy;
}; };
class reduction : public template_base_impl<reduction, reduction_parameters> class reduction : public base_impl<reduction, reduction_parameters>
{ {
private: private:
unsigned int lmem_usage(symbolic_expressions_container const & symbolic_expressions) const; unsigned int lmem_usage(symbolic_expressions_container const & symbolic_expressions) const;

View File

@@ -1,12 +1,12 @@
#ifndef ATIDLAS_BACKEND_TEMPLATES_VAXPY_H #ifndef ATIDLAS_BACKEND_TEMPLATES_VAXPY_H
#define ATIDLAS_BACKEND_TEMPLATES_VAXPY_H #define ATIDLAS_BACKEND_TEMPLATES_VAXPY_H
#include "atidlas/backend/templates/template_base.h" #include "atidlas/backend/templates/base.h"
namespace atidlas namespace atidlas
{ {
class vaxpy_parameters : public template_base::parameters_type class vaxpy_parameters : public base::parameters_type
{ {
public: public:
vaxpy_parameters(unsigned int _simd_width, unsigned int _group_size, unsigned int _num_groups, fetching_policy_type _fetching_policy); vaxpy_parameters(unsigned int _simd_width, unsigned int _group_size, unsigned int _num_groups, fetching_policy_type _fetching_policy);
@@ -14,7 +14,7 @@ public:
fetching_policy_type fetching_policy; fetching_policy_type fetching_policy;
}; };
class vaxpy : public template_base_impl<vaxpy, vaxpy_parameters> class vaxpy : public base_impl<vaxpy, vaxpy_parameters>
{ {
private: private:
virtual int check_invalid_impl(cl::Device const &, symbolic_expressions_container const &) const; virtual int check_invalid_impl(cl::Device const &, symbolic_expressions_container const &) const;

View File

@@ -5,7 +5,7 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include "atidlas/backend/templates/template_base.h" #include "atidlas/backend/templates/base.h"
#include "atidlas/cl/compare.hpp" #include "atidlas/cl/compare.hpp"
#include "atidlas/cl/lazy_compiler.h" #include "atidlas/cl/lazy_compiler.h"
#include "atidlas/model/predictors/random_forest.h" #include "atidlas/model/predictors/random_forest.h"
@@ -16,7 +16,7 @@ namespace atidlas
class model class model
{ {
typedef std::vector< tools::shared_ptr<template_base> > templates_container; typedef std::vector< tools::shared_ptr<base> > templates_container;
private: private:
std::string define_extension(std::string const & extensions, std::string const & ext); std::string define_extension(std::string const & extensions, std::string const & ext);
@@ -24,9 +24,9 @@ namespace atidlas
std::vector<cl::lazy_compiler>& init(symbolic_expressions_container const & symbolic_expressions, cl::Context const & context, cl::Device const & device, bool force_recompilation); std::vector<cl::lazy_compiler>& init(symbolic_expressions_container const & symbolic_expressions, cl::Context const & context, cl::Device const & device, bool force_recompilation);
public: public:
model(predictors::random_forest const &, std::vector< tools::shared_ptr<template_base> > const &, cl::CommandQueue &); model(predictors::random_forest const &, std::vector< tools::shared_ptr<base> > const &, cl::CommandQueue &);
model(std::vector< tools::shared_ptr<template_base> > const &, cl::CommandQueue &); model(std::vector< tools::shared_ptr<base> > const &, cl::CommandQueue &);
model(template_base const &, cl::CommandQueue &); model(base const &, cl::CommandQueue &);
void execute(symbolic_expressions_container const &, bool bypass_predictor = false, bool force_recompilation = false); void execute(symbolic_expressions_container const &, bool bypass_predictor = false, bool force_recompilation = false);
void tune(symbolic_expressions_container const &); void tune(symbolic_expressions_container const &);

View File

@@ -12,7 +12,7 @@ namespace atidlas
{ {
class array; class array;
class array_repeat_infos; class repeat_infos;
/** @brief Optimization enum for grouping operations into unary or binary operations. Just for optimization of lookups. */ /** @brief Optimization enum for grouping operations into unary or binary operations. Just for optimization of lookups. */
enum operation_node_type_family enum operation_node_type_family
@@ -99,11 +99,12 @@ enum operation_node_type
OPERATOR_ELEMENT_MAX_TYPE, OPERATOR_ELEMENT_MAX_TYPE,
OPERATOR_ELEMENT_MIN_TYPE, OPERATOR_ELEMENT_MIN_TYPE,
OPERATOR_OUTER_PROD_TYPE,
OPERATOR_MATRIX_DIAG_TYPE, OPERATOR_MATRIX_DIAG_TYPE,
OPERATOR_MATRIX_ROW_TYPE, OPERATOR_MATRIX_ROW_TYPE,
OPERATOR_MATRIX_COLUMN_TYPE, OPERATOR_MATRIX_COLUMN_TYPE,
OPERATOR_MATRIX_REPEAT_TYPE, OPERATOR_REPEAT_TYPE,
OPERATOR_VECTOR_DIAG_TYPE, OPERATOR_VDIAG_TYPE,
OPERATOR_MATRIX_PRODUCT_NN_TYPE, OPERATOR_MATRIX_PRODUCT_NN_TYPE,
OPERATOR_MATRIX_PRODUCT_TN_TYPE, OPERATOR_MATRIX_PRODUCT_TN_TYPE,
@@ -129,7 +130,7 @@ enum symbolic_expression_node_subtype
INVALID_SUBTYPE = 0, INVALID_SUBTYPE = 0,
VALUE_SCALAR_TYPE, VALUE_SCALAR_TYPE,
DENSE_ARRAY_TYPE, DENSE_ARRAY_TYPE,
MATRIX_REPEAT_INFOS_TYPE REPEAT_INFOS_TYPE
}; };
struct lhs_rhs_element struct lhs_rhs_element
@@ -138,7 +139,7 @@ struct lhs_rhs_element
lhs_rhs_element(unsigned int _node_index); lhs_rhs_element(unsigned int _node_index);
lhs_rhs_element(atidlas::array const & x); lhs_rhs_element(atidlas::array const & x);
lhs_rhs_element(value_scalar const & x); lhs_rhs_element(value_scalar const & x);
lhs_rhs_element(array_repeat_infos const & x); lhs_rhs_element(repeat_infos const & x);
symbolic_expression_node_type_family type_family; symbolic_expression_node_type_family type_family;
symbolic_expression_node_subtype subtype; symbolic_expression_node_subtype subtype;
@@ -149,7 +150,7 @@ struct lhs_rhs_element
unsigned int node_index; unsigned int node_index;
atidlas::array * array; atidlas::array * array;
values_holder vscalar; values_holder vscalar;
array_repeat_infos * repeat_infos; atidlas::repeat_infos * tuple;
}; };
}; };

View File

@@ -7,10 +7,10 @@
namespace atidlas namespace atidlas
{ {
inline std::string to_string(symbolic_expression_node_subtype const & f); std::string to_string(symbolic_expression_node_subtype const & f);
inline std::string to_string(lhs_rhs_element const & e); std::string to_string(lhs_rhs_element const & e);
inline std::ostream & operator<<(std::ostream & os, symbolic_expression_node const & s_node); std::ostream & operator<<(std::ostream & os, symbolic_expression_node const & s_node);
inline std::string to_string(atidlas::symbolic_expression const & s); std::string to_string(atidlas::symbolic_expression const & s);
} }

View File

@@ -347,6 +347,7 @@ bool check_elementwise(U const & u, V const & v)
return max(u.shape())==1 || max(v.shape())==1 || u.shape()==v.shape(); return max(u.shape())==1 || max(v.shape())==1 || u.shape()==v.shape();
} }
#define DEFINE_ELEMENT_BINARY_OPERATOR(OP, OPNAME) \ #define DEFINE_ELEMENT_BINARY_OPERATOR(OP, OPNAME) \
array_expression OPNAME (array_expression const & x, array_expression const & y) \ array_expression OPNAME (array_expression const & x, array_expression const & y) \
{ assert(check_elementwise(x, y));\ { assert(check_elementwise(x, y));\
@@ -392,6 +393,12 @@ DEFINE_ELEMENT_BINARY_OPERATOR(OPERATOR_ELEMENT_MAX_TYPE, max)
DEFINE_ELEMENT_BINARY_OPERATOR(OPERATOR_ELEMENT_MIN_TYPE, min) DEFINE_ELEMENT_BINARY_OPERATOR(OPERATOR_ELEMENT_MIN_TYPE, min)
DEFINE_ELEMENT_BINARY_OPERATOR(OPERATOR_ELEMENT_POW_TYPE, pow) DEFINE_ELEMENT_BINARY_OPERATOR(OPERATOR_ELEMENT_POW_TYPE, pow)
array_expression outer(array const & x, array const & y)
{
assert(x.nshape()==1 && y.nshape()==1);
return array_expression(x, y, op_element(OPERATOR_BINARY_TYPE_FAMILY, OPERATOR_OUTER_PROD_TYPE), x.context(), x.dtype(), size4(max(x.shape()), max(y.shape())) );
}
namespace detail namespace detail
{ {
DEFINE_ELEMENT_BINARY_OPERATOR(OPERATOR_ASSIGN_TYPE, assign) DEFINE_ELEMENT_BINARY_OPERATOR(OPERATOR_ASSIGN_TYPE, assign)
@@ -433,7 +440,7 @@ DEFINE_ELEMENT_UNARY_OPERATOR(OPERATOR_TANH_TYPE, tanh)
////--------------------------------------- ////---------------------------------------
atidlas::array_expression eye(std::size_t M, std::size_t N, atidlas::numeric_type dtype, cl::Context ctx) atidlas::array_expression eye(std::size_t M, std::size_t N, atidlas::numeric_type dtype, cl::Context ctx)
{ {
return array_expression(value_scalar(1), value_scalar(0), op_element(OPERATOR_UNARY_TYPE_FAMILY, OPERATOR_VECTOR_DIAG_TYPE), ctx, dtype, size4(M, N)); return array_expression(value_scalar(1), value_scalar(0), op_element(OPERATOR_UNARY_TYPE_FAMILY, OPERATOR_VDIAG_TYPE), ctx, dtype, size4(M, N));
} }
inline size4 trans(size4 const & shape) inline size4 trans(size4 const & shape)
@@ -450,18 +457,18 @@ array_expression trans(array_expression const & x) \
array_expression repmat(array const & A, int_t const & rep1, int_t const & rep2) array_expression repmat(array const & A, int_t const & rep1, int_t const & rep2)
{ {
static array_repeat_infos infos(A.shape(), size4(rep1, rep2)); static repeat_infos infos(A.shape(), size4(rep1, rep2));
infos = array_repeat_infos(A.shape(), size4(rep1, rep2)); infos = repeat_infos(A.shape(), size4(rep1, rep2));
size4 newshape = prod(infos.sub, infos.rep); size4 newshape = prod(infos.sub, infos.rep);
return array_expression(A, infos, op_element(OPERATOR_BINARY_TYPE_FAMILY, OPERATOR_MATRIX_REPEAT_TYPE), A.context(), A.dtype(), newshape); return array_expression(A, infos, op_element(OPERATOR_BINARY_TYPE_FAMILY, OPERATOR_REPEAT_TYPE), A.context(), A.dtype(), newshape);
} }
array_expression repmat(array_expression const & A, int_t const & rep1, int_t const & rep2) array_expression repmat(array_expression const & A, int_t const & rep1, int_t const & rep2)
{ {
static array_repeat_infos infos(A.shape(), size4(rep1, rep2)); static repeat_infos infos(A.shape(), size4(rep1, rep2));
infos = array_repeat_infos(A.shape(), size4(rep1, rep2)); infos = repeat_infos(A.shape(), size4(rep1, rep2));
size4 newshape = prod(infos.sub, infos.rep); size4 newshape = prod(infos.sub, infos.rep);
return array_expression(A, infos, op_element(OPERATOR_BINARY_TYPE_FAMILY, OPERATOR_MATRIX_REPEAT_TYPE), newshape); return array_expression(A, infos, op_element(OPERATOR_BINARY_TYPE_FAMILY, OPERATOR_REPEAT_TYPE), newshape);
} }
////--------------------------------------- ////---------------------------------------
@@ -631,6 +638,7 @@ DEFINE_DOT(array_expression, array_expression)
#undef DEFINE_DOT #undef DEFINE_DOT
#define DEFINE_NORM(TYPE)\ #define DEFINE_NORM(TYPE)\
array_expression norm(TYPE const & x, unsigned int order)\ array_expression norm(TYPE const & x, unsigned int order)\
{\ {\

View File

@@ -13,9 +13,10 @@
namespace atidlas namespace atidlas
{ {
void mapped_object::preprocess(std::string &) const { } void mapped_object::preprocess(std::string &) const { }
void mapped_object::postprocess(std::string &) const { }
void mapped_object::replace_macro(std::string & str, std::string const & macro, MorphBase const & morph) void mapped_object::replace_macro(std::string & str, std::string const & macro, MorphBase const & morph)
{ {
size_t pos = 0; size_t pos = 0;
@@ -75,6 +76,7 @@ std::string mapped_object::process(std::string const & in) const
preprocess(res); preprocess(res);
for (std::map<std::string,std::string>::const_iterator it = keywords_.begin(); it != keywords_.end(); ++it) for (std::map<std::string,std::string>::const_iterator it = keywords_.begin(); it != keywords_.end(); ++it)
tools::find_and_replace(res, it->first, it->second); tools::find_and_replace(res, it->first, it->second);
postprocess(res);
return res; return res;
} }
@@ -88,7 +90,7 @@ std::string mapped_object::evaluate(std::map<std::string, std::string> const & a
binary_leaf::binary_leaf(mapped_object::node_info info) : info_(info){ } binary_leaf::binary_leaf(mapped_object::node_info info) : info_(info){ }
void binary_leaf::process_recursive(kernel_generation_stream & stream, leaf_t leaf, std::multimap<std::string, std::string> const & accessors) void binary_leaf::process_recursive(kernel_generation_stream & stream, leaf_t leaf, std::map<std::string, std::string> const & accessors)
{ {
std::set<std::string> already_fetched; std::set<std::string> already_fetched;
process(stream, leaf, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping, already_fetched); process(stream, leaf, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping, already_fetched);
@@ -232,20 +234,19 @@ mapped_array::mapped_array(std::string const & scalartype, unsigned int id, char
} }
// //
void mapped_vector_diag::preprocess(std::string &res) const void mapped_vdiag::postprocess(std::string &res) const
{ {
std::map<std::string, std::string> accessors; std::map<std::string, std::string> accessors;
tools::find_and_replace(res, "#diag_offset", atidlas::evaluate(RHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping)); tools::find_and_replace(res, "#diag_offset", atidlas::evaluate(RHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping));
accessors["array"] = res; accessors["array"] = res;
accessors["host_scalar"] = res; accessors["host_scalar"] = res;
res = atidlas::evaluate(LHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping); res = atidlas::evaluate(LHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping);
std::cout << res << std::endl;
} }
mapped_vector_diag::mapped_vector_diag(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "vector_diag"), binary_leaf(info){} mapped_vdiag::mapped_vdiag(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "vdiag"), binary_leaf(info){}
// //
void mapped_trans::preprocess(std::string &res) const void mapped_trans::postprocess(std::string &res) const
{ {
std::map<std::string, std::string> accessors; std::map<std::string, std::string> accessors;
accessors["array"] = res; accessors["array"] = res;
@@ -255,7 +256,7 @@ void mapped_trans::preprocess(std::string &res) const
mapped_trans::mapped_trans(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "matrix_trans"), binary_leaf(info){ } mapped_trans::mapped_trans(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "matrix_trans"), binary_leaf(info){ }
// //
void mapped_matrix_row::preprocess(std::string &res) const void mapped_matrix_row::postprocess(std::string &res) const
{ {
std::map<std::string, std::string> accessors; std::map<std::string, std::string> accessors;
tools::find_and_replace(res, "#row", atidlas::evaluate(RHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping)); tools::find_and_replace(res, "#row", atidlas::evaluate(RHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping));
@@ -267,7 +268,7 @@ mapped_matrix_row::mapped_matrix_row(std::string const & scalartype, unsigned in
{ } { }
// //
void mapped_matrix_column::preprocess(std::string &res) const void mapped_matrix_column::postprocess(std::string &res) const
{ {
std::map<std::string, std::string> accessors; std::map<std::string, std::string> accessors;
tools::find_and_replace(res, "#column", atidlas::evaluate(RHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping)); tools::find_and_replace(res, "#column", atidlas::evaluate(RHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping));
@@ -279,25 +280,24 @@ mapped_matrix_column::mapped_matrix_column(std::string const & scalartype, unsig
{ } { }
// //
void mapped_matrix_repeat::preprocess(std::string &res) const void mapped_repeat::postprocess(std::string &res) const
{ {
std::map<std::string, std::string> accessors; std::map<std::string, std::string> accessors;
mapped_object& args = *(info_.mapping->at(std::make_pair(info_.root_idx,RHS_NODE_TYPE))); mapped_object& args = *(info_.mapping->at(std::make_pair(info_.root_idx,RHS_NODE_TYPE)));
tools::find_and_replace(res, "#tuplearg0", args.process("#tuplearg0"));
tools::find_and_replace(res, "#tuplearg1", args.process("#tuplearg1")); tools::find_and_replace(res, "#tuplearg1", args.process("#tuplearg1"));
tools::find_and_replace(res, "#tuplearg2", args.process("#tuplearg2")); tools::find_and_replace(res, "#tuplearg2", args.process("#tuplearg2"));
tools::find_and_replace(res, "#tuplearg3", args.process("#tuplearg3")); tools::find_and_replace(res, "#tuplearg3", args.process("#tuplearg3"));
tools::find_and_replace(res, "#tuplearg4", args.process("#tuplearg4"));
accessors["array"] = res; accessors["array"] = res;
res = atidlas::evaluate(LHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping); res = atidlas::evaluate(LHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping);
} }
mapped_matrix_repeat::mapped_matrix_repeat(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "matrix_repeat"), binary_leaf(info) mapped_repeat::mapped_repeat(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "repeat"), binary_leaf(info)
{ {}
}
// //
void mapped_matrix_diag::preprocess(std::string &res) const void mapped_matrix_diag::postprocess(std::string &res) const
{ {
std::map<std::string, std::string> accessors; std::map<std::string, std::string> accessors;
tools::find_and_replace(res, "#diag_offset", atidlas::evaluate(RHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping)); tools::find_and_replace(res, "#diag_offset", atidlas::evaluate(RHS_NODE_TYPE, accessors, *info_.symbolic_expression, info_.root_idx, *info_.mapping));
@@ -308,6 +308,29 @@ void mapped_matrix_diag::preprocess(std::string &res) const
mapped_matrix_diag::mapped_matrix_diag(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "matrix_diag"), binary_leaf(info) mapped_matrix_diag::mapped_matrix_diag(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "matrix_diag"), binary_leaf(info)
{ } { }
//
void mapped_outer::postprocess(std::string &res) const
{
struct Morph : public MorphBase
{
Morph(leaf_t const & leaf, node_info const & i) : leaf_(leaf), i_(i){}
std::string operator()(std::string const & i) const
{
std::map<std::string, std::string> accessors;
accessors["array"] = "$VALUE{"+i+"}";
return atidlas::evaluate(leaf_, accessors, *i_.symbolic_expression, i_.root_idx, *i_.mapping);
}
std::string operator()(std::string const &, std::string const &) const{return "";}
private:
leaf_t leaf_;
node_info i_;
};
replace_macro(res, "$LVALUE", Morph(LHS_NODE_TYPE, info_));
replace_macro(res, "$RVALUE", Morph(RHS_NODE_TYPE, info_));
}
mapped_outer::mapped_outer(std::string const & scalartype, unsigned int id, node_info info) : mapped_object(scalartype, id, "outer"), binary_leaf(info)
{ }
} }

View File

@@ -13,13 +13,14 @@ namespace detail
return op.type==OPERATOR_TRANS_TYPE return op.type==OPERATOR_TRANS_TYPE
|| op.type_family==OPERATOR_MATRIX_PRODUCT_TYPE_FAMILY || op.type_family==OPERATOR_MATRIX_PRODUCT_TYPE_FAMILY
|| op.type==OPERATOR_MATRIX_DIAG_TYPE || op.type==OPERATOR_MATRIX_DIAG_TYPE
|| op.type==OPERATOR_VECTOR_DIAG_TYPE || op.type==OPERATOR_VDIAG_TYPE
|| op.type==OPERATOR_MATRIX_REPEAT_TYPE || op.type==OPERATOR_REPEAT_TYPE
|| op.type==OPERATOR_MATRIX_ROW_TYPE || op.type==OPERATOR_MATRIX_ROW_TYPE
|| op.type==OPERATOR_MATRIX_COLUMN_TYPE || op.type==OPERATOR_MATRIX_COLUMN_TYPE
|| op.type_family==OPERATOR_VECTOR_REDUCTION_TYPE_FAMILY || op.type_family==OPERATOR_VECTOR_REDUCTION_TYPE_FAMILY
|| op.type_family==OPERATOR_ROWS_REDUCTION_TYPE_FAMILY || op.type_family==OPERATOR_ROWS_REDUCTION_TYPE_FAMILY
|| op.type_family==OPERATOR_COLUMNS_REDUCTION_TYPE_FAMILY; || op.type_family==OPERATOR_COLUMNS_REDUCTION_TYPE_FAMILY
|| op.type==OPERATOR_OUTER_PROD_TYPE;
} }
bool is_scalar_reduction(symbolic_expression_node const & node) bool is_scalar_reduction(symbolic_expression_node const & node)
@@ -211,7 +212,7 @@ const char * evaluate(operation_node_type type)
case OPERATOR_MATRIX_PRODUCT_TN_TYPE : return "prodTN"; case OPERATOR_MATRIX_PRODUCT_TN_TYPE : return "prodTN";
case OPERATOR_MATRIX_PRODUCT_NT_TYPE : return "prodNT"; case OPERATOR_MATRIX_PRODUCT_NT_TYPE : return "prodNT";
case OPERATOR_MATRIX_PRODUCT_TT_TYPE : return "prodTT"; case OPERATOR_MATRIX_PRODUCT_TT_TYPE : return "prodTT";
case OPERATOR_VECTOR_DIAG_TYPE : return "vdiag"; case OPERATOR_VDIAG_TYPE : return "vdiag";
case OPERATOR_MATRIX_DIAG_TYPE : return "mdiag"; case OPERATOR_MATRIX_DIAG_TYPE : return "mdiag";
case OPERATOR_MATRIX_ROW_TYPE : return "row"; case OPERATOR_MATRIX_ROW_TYPE : return "row";
case OPERATOR_MATRIX_COLUMN_TYPE : return "col"; case OPERATOR_MATRIX_COLUMN_TYPE : return "col";
@@ -339,7 +340,7 @@ void evaluate(kernel_generation_stream & stream, leaf_t leaf, std::map<std::stri
stream << evaluate(leaf, accessors, **sit, (*sit)->root(), *mit) << ";" << std::endl; stream << evaluate(leaf, accessors, **sit, (*sit)->root(), *mit) << ";" << std::endl;
} }
process_traversal::process_traversal(std::multimap<std::string, std::string> const & accessors, kernel_generation_stream & stream, process_traversal::process_traversal(std::map<std::string, std::string> const & accessors, kernel_generation_stream & stream,
mapping_type const & mapping, std::set<std::string> & already_processed) : mapping_type const & mapping, std::set<std::string> & already_processed) :
accessors_(accessors), stream_(stream), mapping_(mapping), already_processed_(already_processed) accessors_(accessors), stream_(stream), mapping_(mapping), already_processed_(already_processed)
{ } { }
@@ -351,19 +352,24 @@ void process_traversal::operator()(symbolic_expression const & /*symbolic_expres
{ {
mapped_object * obj = it->second.get(); mapped_object * obj = it->second.get();
std::string name = obj->name(); std::string name = obj->name();
if(accessors_.find(name)!=accessors_.end() && already_processed_.insert(obj->process("#name")).second)
for(std::multimap<std::string, std::string>::const_iterator it = accessors_.lower_bound(name) ; it != accessors_.upper_bound(name) ; ++it) if(accessors_.find(name)!=accessors_.end() && already_processed_.insert(name).second)
stream_ << obj->process(it->second) << std::endl; for(std::map<std::string, std::string>::const_iterator itt = accessors_.lower_bound(name) ; itt != accessors_.upper_bound(name) ; ++itt)
{
stream_ << obj->process(itt->second) << std::endl;
}
std::string key = obj->type_key(); std::string key = obj->type_key();
if(accessors_.find(key)!=accessors_.end() && already_processed_.insert(obj->process("#name")).second) if(accessors_.find(key)!=accessors_.end() && already_processed_.insert(name).second)
for(std::multimap<std::string, std::string>::const_iterator it = accessors_.lower_bound(key) ; it != accessors_.upper_bound(key) ; ++it) for(std::map<std::string, std::string>::const_iterator itt = accessors_.lower_bound(key) ; itt != accessors_.upper_bound(key) ; ++itt)
stream_ << obj->process(it->second) << std::endl; {
stream_ << obj->process(itt->second) << std::endl;
}
} }
} }
void process(kernel_generation_stream & stream, leaf_t leaf, std::multimap<std::string, std::string> const & accessors, void process(kernel_generation_stream & stream, leaf_t leaf, std::map<std::string, std::string> const & accessors,
atidlas::symbolic_expression const & symbolic_expression, size_t root_idx, mapping_type const & mapping, std::set<std::string> & already_processed) atidlas::symbolic_expression const & symbolic_expression, size_t root_idx, mapping_type const & mapping, std::set<std::string> & already_processed)
{ {
process_traversal traversal_functor(accessors, stream, mapping, already_processed); process_traversal traversal_functor(accessors, stream, mapping, already_processed);
@@ -389,7 +395,7 @@ void process(kernel_generation_stream & stream, leaf_t leaf, std::multimap<std::
} }
} }
void process(kernel_generation_stream & stream, leaf_t leaf, std::multimap<std::string, std::string> const & accessors, void process(kernel_generation_stream & stream, leaf_t leaf, std::map<std::string, std::string> const & accessors,
symbolic_expressions_container const & symbolic_expressions, std::vector<mapping_type> const & mappings) symbolic_expressions_container const & symbolic_expressions, std::vector<mapping_type> const & mappings)
{ {
symbolic_expressions_container::data_type::const_iterator sit; symbolic_expressions_container::data_type::const_iterator sit;

View File

@@ -6,19 +6,20 @@
#include "atidlas/backend/templates/maxpy.h" #include "atidlas/backend/templates/maxpy.h"
#include "atidlas/backend/templates/mreduction.h" #include "atidlas/backend/templates/mreduction.h"
#include "atidlas/backend/templates/mproduct.h" #include "atidlas/backend/templates/mproduct.h"
#include "atidlas/backend/templates/template_base.h" #include "atidlas/backend/templates/base.h"
#include "atidlas/backend/parse.h" #include "atidlas/backend/parse.h"
#include "atidlas/exception/operation_not_supported.h" #include "atidlas/exception/operation_not_supported.h"
#include "atidlas/tools/to_string.hpp" #include "atidlas/tools/to_string.hpp"
#include "atidlas/tools/make_map.hpp" #include "atidlas/tools/make_map.hpp"
#include "atidlas/symbolic/io.h"
namespace atidlas namespace atidlas
{ {
template_base::parameters_type::parameters_type(unsigned int _simd_width, int_t _local_size_1, int_t _local_size_2, int_t _num_kernels) : simd_width(_simd_width), local_size_0(_local_size_1), local_size_1(_local_size_2), num_kernels(_num_kernels) base::parameters_type::parameters_type(unsigned int _simd_width, int_t _local_size_1, int_t _local_size_2, int_t _num_kernels) : simd_width(_simd_width), local_size_0(_local_size_1), local_size_1(_local_size_2), num_kernels(_num_kernels)
{ } { }
numeric_type template_base::map_functor::get_numeric_type(atidlas::symbolic_expression const * symbolic_expression, int_t root_idx) const numeric_type base::map_functor::get_numeric_type(atidlas::symbolic_expression const * symbolic_expression, int_t root_idx) const
{ {
symbolic_expression_node const * root_node = &symbolic_expression->tree()[root_idx]; symbolic_expression_node const * root_node = &symbolic_expression->tree()[root_idx];
while (root_node->lhs.dtype==INVALID_NUMERIC_TYPE) while (root_node->lhs.dtype==INVALID_NUMERIC_TYPE)
@@ -28,20 +29,20 @@ numeric_type template_base::map_functor::get_numeric_type(atidlas::symbolic_expr
/** @brief Binary leaf */ /** @brief Binary leaf */
template<class T> template<class T>
tools::shared_ptr<mapped_object> template_base::map_functor::binary_leaf(atidlas::symbolic_expression const * symbolic_expression, int_t root_idx, mapping_type const * mapping) const tools::shared_ptr<mapped_object> base::map_functor::binary_leaf(atidlas::symbolic_expression const * symbolic_expression, int_t root_idx, mapping_type const * mapping) const
{ {
return tools::shared_ptr<mapped_object>(new T(numeric_type_to_string(symbolic_expression->dtype()), binder_.get(NULL), mapped_object::node_info(mapping, symbolic_expression, root_idx))); return tools::shared_ptr<mapped_object>(new T(numeric_type_to_string(symbolic_expression->dtype()), binder_.get(NULL), mapped_object::node_info(mapping, symbolic_expression, root_idx)));
} }
/** @brief Scalar mapping */ /** @brief Scalar mapping */
tools::shared_ptr<mapped_object> template_base::map_functor::create(numeric_type dtype, values_holder) const tools::shared_ptr<mapped_object> base::map_functor::create(numeric_type dtype, values_holder) const
{ {
std::string strdtype = numeric_type_to_string(dtype); std::string strdtype = numeric_type_to_string(dtype);
return tools::shared_ptr<mapped_object>(new mapped_host_scalar(strdtype, binder_.get(NULL))); return tools::shared_ptr<mapped_object>(new mapped_host_scalar(strdtype, binder_.get(NULL)));
} }
/** @brief Vector mapping */ /** @brief Vector mapping */
tools::shared_ptr<mapped_object> template_base::map_functor::create(array const & a) const tools::shared_ptr<mapped_object> base::map_functor::create(array const & a) const
{ {
std::string dtype = numeric_type_to_string(a.dtype()); std::string dtype = numeric_type_to_string(a.dtype());
unsigned int id = binder_.get(&a.data()); unsigned int id = binder_.get(&a.data());
@@ -61,17 +62,17 @@ tools::shared_ptr<mapped_object> template_base::map_functor::create(array const
} }
} }
tools::shared_ptr<mapped_object> template_base::map_functor::create(array_repeat_infos const &) const tools::shared_ptr<mapped_object> base::map_functor::create(repeat_infos const &) const
{ {
//TODO: Make it less specific! //TODO: Make it less specific!
return tools::shared_ptr<mapped_object>(new mapped_tuple("int",binder_.get(NULL),4)); return tools::shared_ptr<mapped_object>(new mapped_tuple("int",binder_.get(NULL),4));
} }
tools::shared_ptr<mapped_object> template_base::map_functor::create(lhs_rhs_element const & lhs_rhs) const tools::shared_ptr<mapped_object> base::map_functor::create(lhs_rhs_element const & lhs_rhs) const
{ {
switch(lhs_rhs.type_family) switch(lhs_rhs.type_family)
{ {
case INFOS_TYPE_FAMILY: return create(*lhs_rhs.repeat_infos); case INFOS_TYPE_FAMILY: return create(*lhs_rhs.tuple);
case VALUE_TYPE_FAMILY: return create(lhs_rhs.dtype, lhs_rhs.vscalar); case VALUE_TYPE_FAMILY: return create(lhs_rhs.dtype, lhs_rhs.vscalar);
case ARRAY_TYPE_FAMILY: return create(*lhs_rhs.array); case ARRAY_TYPE_FAMILY: return create(*lhs_rhs.array);
default: throw ""; default: throw "";
@@ -79,10 +80,10 @@ tools::shared_ptr<mapped_object> template_base::map_functor::create(lhs_rhs_elem
} }
template_base::map_functor::map_functor(symbolic_binder & binder, mapping_type & mapping) : binder_(binder), mapping_(mapping){ } base::map_functor::map_functor(symbolic_binder & binder, mapping_type & mapping) : binder_(binder), mapping_(mapping){ }
/** @brief Traversal functor */ /** @brief Traversal functor */
void template_base::map_functor::operator()(atidlas::symbolic_expression const & symbolic_expression, int_t root_idx, leaf_t leaf_t) const { void base::map_functor::operator()(atidlas::symbolic_expression const & symbolic_expression, int_t root_idx, leaf_t leaf_t) const {
mapping_type::key_type key(root_idx, leaf_t); mapping_type::key_type key(root_idx, leaf_t);
symbolic_expression_node const & root_node = symbolic_expression.tree()[root_idx]; symbolic_expression_node const & root_node = symbolic_expression.tree()[root_idx];
@@ -92,8 +93,8 @@ void template_base::map_functor::operator()(atidlas::symbolic_expression const &
mapping_.insert(mapping_type::value_type(key, create(root_node.rhs))); mapping_.insert(mapping_type::value_type(key, create(root_node.rhs)));
else if ( leaf_t== PARENT_NODE_TYPE) else if ( leaf_t== PARENT_NODE_TYPE)
{ {
if (root_node.op.type==OPERATOR_VECTOR_DIAG_TYPE) if (root_node.op.type==OPERATOR_VDIAG_TYPE)
mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_vector_diag>(&symbolic_expression, root_idx, &mapping_))); mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_vdiag>(&symbolic_expression, root_idx, &mapping_)));
else if (root_node.op.type==OPERATOR_MATRIX_DIAG_TYPE) else if (root_node.op.type==OPERATOR_MATRIX_DIAG_TYPE)
mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_matrix_diag>(&symbolic_expression, root_idx, &mapping_))); mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_matrix_diag>(&symbolic_expression, root_idx, &mapping_)));
else if (root_node.op.type==OPERATOR_MATRIX_ROW_TYPE) else if (root_node.op.type==OPERATOR_MATRIX_ROW_TYPE)
@@ -108,16 +109,17 @@ void template_base::map_functor::operator()(atidlas::symbolic_expression const &
mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_mproduct>(&symbolic_expression, root_idx, &mapping_))); mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_mproduct>(&symbolic_expression, root_idx, &mapping_)));
else if (root_node.op.type == OPERATOR_TRANS_TYPE) else if (root_node.op.type == OPERATOR_TRANS_TYPE)
mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_trans>(&symbolic_expression, root_idx, &mapping_))); mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_trans>(&symbolic_expression, root_idx, &mapping_)));
else if (root_node.op.type == OPERATOR_MATRIX_REPEAT_TYPE){ else if (root_node.op.type == OPERATOR_REPEAT_TYPE)
mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_matrix_repeat>(&symbolic_expression, root_idx, &mapping_))); mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_repeat>(&symbolic_expression, root_idx, &mapping_)));
} else if (root_node.op.type == OPERATOR_OUTER_PROD_TYPE)
mapping_.insert(mapping_type::value_type(key, binary_leaf<mapped_outer>(&symbolic_expression, root_idx, &mapping_)));
} }
} }
template_base::set_arguments_functor::set_arguments_functor(symbolic_binder & binder, unsigned int & current_arg, cl::Kernel & kernel) : base::set_arguments_functor::set_arguments_functor(symbolic_binder & binder, unsigned int & current_arg, cl::Kernel & kernel) :
binder_(binder), current_arg_(current_arg), kernel_(kernel){ } binder_(binder), current_arg_(current_arg), kernel_(kernel){ }
void template_base::set_arguments_functor::set_arguments(numeric_type dtype, values_holder const & scal) const void base::set_arguments_functor::set_arguments(numeric_type dtype, values_holder const & scal) const
{ {
switch(dtype) switch(dtype)
{ {
@@ -136,7 +138,7 @@ void template_base::set_arguments_functor::set_arguments(numeric_type dtype, val
} }
/** @brief Vector mapping */ /** @brief Vector mapping */
void template_base::set_arguments_functor::set_arguments(array const & x) const void base::set_arguments_functor::set_arguments(array const & x) const
{ {
bool is_bound = binder_.bind(&x.data()); bool is_bound = binder_.bind(&x.data());
if (is_bound) if (is_bound)
@@ -159,7 +161,7 @@ void template_base::set_arguments_functor::set_arguments(array const & x) const
} }
} }
void template_base::set_arguments_functor::set_arguments(array_repeat_infos const & i) const void base::set_arguments_functor::set_arguments(repeat_infos const & i) const
{ {
kernel_.setArg(current_arg_++, cl_uint(i.sub._1)); kernel_.setArg(current_arg_++, cl_uint(i.sub._1));
kernel_.setArg(current_arg_++, cl_uint(i.sub._2)); kernel_.setArg(current_arg_++, cl_uint(i.sub._2));
@@ -167,19 +169,19 @@ void template_base::set_arguments_functor::set_arguments(array_repeat_infos cons
kernel_.setArg(current_arg_++, cl_uint(i.rep._2)); kernel_.setArg(current_arg_++, cl_uint(i.rep._2));
} }
void template_base::set_arguments_functor::set_arguments(lhs_rhs_element const & lhs_rhs) const void base::set_arguments_functor::set_arguments(lhs_rhs_element const & lhs_rhs) const
{ {
switch(lhs_rhs.type_family) switch(lhs_rhs.type_family)
{ {
case VALUE_TYPE_FAMILY: return set_arguments(lhs_rhs.dtype, lhs_rhs.vscalar); case VALUE_TYPE_FAMILY: return set_arguments(lhs_rhs.dtype, lhs_rhs.vscalar);
case ARRAY_TYPE_FAMILY: return set_arguments(*lhs_rhs.array); case ARRAY_TYPE_FAMILY: return set_arguments(*lhs_rhs.array);
case INFOS_TYPE_FAMILY: return set_arguments(*lhs_rhs.repeat_infos); case INFOS_TYPE_FAMILY: return set_arguments(*lhs_rhs.tuple);
default: throw "oh noez"; default: throw "oh noez";
} }
} }
/** @brief Traversal functor: */ /** @brief Traversal functor: */
void template_base::set_arguments_functor::operator()(atidlas::symbolic_expression const & symbolic_expression, int_t root_idx, leaf_t leaf_t) const void base::set_arguments_functor::operator()(atidlas::symbolic_expression const & symbolic_expression, int_t root_idx, leaf_t leaf_t) const
{ {
symbolic_expression_node const & root_node = symbolic_expression.tree()[root_idx]; symbolic_expression_node const & root_node = symbolic_expression.tree()[root_idx];
if (leaf_t==LHS_NODE_TYPE && root_node.lhs.type_family != COMPOSITE_OPERATOR_FAMILY) if (leaf_t==LHS_NODE_TYPE && root_node.lhs.type_family != COMPOSITE_OPERATOR_FAMILY)
@@ -188,7 +190,7 @@ void template_base::set_arguments_functor::operator()(atidlas::symbolic_expressi
set_arguments(root_node.rhs); set_arguments(root_node.rhs);
} }
void template_base::compute_reduction(kernel_generation_stream & os, std::string acc, std::string cur, op_element const & op) void base::compute_reduction(kernel_generation_stream & os, std::string acc, std::string cur, op_element const & op)
{ {
if (detail::is_elementwise_function(op)) if (detail::is_elementwise_function(op))
os << acc << "=" << evaluate(op.type) << "(" << acc << "," << cur << ");" << std::endl; os << acc << "=" << evaluate(op.type) << "(" << acc << "," << cur << ");" << std::endl;
@@ -196,7 +198,7 @@ void template_base::compute_reduction(kernel_generation_stream & os, std::string
os << acc << "= (" << acc << ")" << evaluate(op.type) << "(" << cur << ");" << std::endl; os << acc << "= (" << acc << ")" << evaluate(op.type) << "(" << cur << ");" << std::endl;
} }
void template_base::compute_index_reduction(kernel_generation_stream & os, std::string acc, std::string cur, std::string const & acc_value, std::string const & cur_value, op_element const & op) void base::compute_index_reduction(kernel_generation_stream & os, std::string acc, std::string cur, std::string const & acc_value, std::string const & cur_value, op_element const & op)
{ {
// os << acc << " = " << cur_value << ">" << acc_value << "?" << cur << ":" << acc << ";" << std::endl; // os << acc << " = " << cur_value << ">" << acc_value << "?" << cur << ":" << acc << ";" << std::endl;
os << acc << "= select(" << acc << "," << cur << "," << cur_value << ">" << acc_value << ");" << std::endl; os << acc << "= select(" << acc << "," << cur << "," << cur_value << ">" << acc_value << ");" << std::endl;
@@ -208,7 +210,7 @@ void template_base::compute_index_reduction(kernel_generation_stream & os, std::
os << "(" << acc_value << "," << cur_value << ");"<< std::endl; os << "(" << acc_value << "," << cur_value << ");"<< std::endl;
} }
void template_base::process_all(std::string const & type_key, std::string const & str, void base::process_all(std::string const & type_key, std::string const & str,
kernel_generation_stream & stream, std::vector<mapping_type> const & mappings) kernel_generation_stream & stream, std::vector<mapping_type> const & mappings)
{ {
for (std::vector<mapping_type>::const_iterator mit = mappings.begin(); mit != mappings.end(); ++mit) for (std::vector<mapping_type>::const_iterator mit = mappings.begin(); mit != mappings.end(); ++mit)
@@ -218,7 +220,7 @@ void template_base::process_all(std::string const & type_key, std::string const
} }
void template_base::template_base::process_all_at(std::string const & type_key, std::string const & str, void base::base::process_all_at(std::string const & type_key, std::string const & str,
kernel_generation_stream & stream, std::vector<mapping_type> const & mappings, kernel_generation_stream & stream, std::vector<mapping_type> const & mappings,
size_t root_idx, leaf_t leaf) size_t root_idx, leaf_t leaf)
{ {
@@ -230,7 +232,7 @@ void template_base::template_base::process_all_at(std::string const & type_key,
} }
} }
std::string template_base::neutral_element(op_element const & op) std::string base::neutral_element(op_element const & op)
{ {
switch (op.type) switch (op.type)
{ {
@@ -250,7 +252,7 @@ std::string template_base::neutral_element(op_element const & op)
} }
} }
std::string template_base::generate_arguments(std::vector<mapping_type> const & mappings, std::multimap<std::string, std::string> const & accessors, symbolic_expressions_container const & symbolic_expressions) std::string base::generate_arguments(std::vector<mapping_type> const & mappings, std::map<std::string, std::string> const & accessors, symbolic_expressions_container const & symbolic_expressions)
{ {
kernel_generation_stream stream; kernel_generation_stream stream;
process(stream, PARENT_NODE_TYPE, accessors, symbolic_expressions, mappings); process(stream, PARENT_NODE_TYPE, accessors, symbolic_expressions, mappings);
@@ -259,9 +261,9 @@ std::string template_base::generate_arguments(std::vector<mapping_type> const &
return res; return res;
} }
std::string template_base::generate_arguments(std::string const & data_type, std::vector<mapping_type> const & mappings, symbolic_expressions_container const & symbolic_expressions) std::string base::generate_arguments(std::string const & data_type, std::vector<mapping_type> const & mappings, symbolic_expressions_container const & symbolic_expressions)
{ {
return generate_arguments(mappings, tools::make_map<std::multimap<std::string, std::string> >("scalar", "__global #scalartype* #pointer,") return generate_arguments(mappings, tools::make_map<std::map<std::string, std::string> >("scalar", "__global #scalartype* #pointer,")
("host_scalar", "#scalartype #name,") ("host_scalar", "#scalartype #name,")
("array", "__global " + data_type + "* #pointer, uint #ld, uint #start1, uint #start2, uint #stride1, uint #stride2,") ("array", "__global " + data_type + "* #pointer, uint #ld, uint #start1, uint #start2, uint #stride1, uint #stride2,")
("tuple4", "#scalartype #name0, #scalartype #name1, #scalartype #name2, #scalartype #name3,"), symbolic_expressions); ("tuple4", "#scalartype #name0, #scalartype #name1, #scalartype #name2, #scalartype #name3,"), symbolic_expressions);
@@ -269,14 +271,14 @@ std::string template_base::generate_arguments(std::string const & data_type, std
void template_base::set_arguments(symbolic_expressions_container const & symbolic_expressions, cl::Kernel & kernel, unsigned int & current_arg) void base::set_arguments(symbolic_expressions_container const & symbolic_expressions, cl::Kernel & kernel, unsigned int & current_arg)
{ {
tools::shared_ptr<symbolic_binder> binder = make_binder(); tools::shared_ptr<symbolic_binder> binder = make_binder();
for (symbolic_expressions_container::data_type::const_iterator itt = symbolic_expressions.data().begin(); itt != symbolic_expressions.data().end(); ++itt) for (symbolic_expressions_container::data_type::const_iterator itt = symbolic_expressions.data().begin(); itt != symbolic_expressions.data().end(); ++itt)
traverse(**itt, (*itt)->root(), set_arguments_functor(*binder, current_arg, kernel), true); traverse(**itt, (*itt)->root(), set_arguments_functor(*binder, current_arg, kernel), true);
} }
void template_base::fill_kernel_name(char * ptr, unsigned int label, const char * suffix) void base::fill_kernel_name(char * ptr, unsigned int label, const char * suffix)
{ {
*ptr++='k'; *ptr++='k';
if (label==0) if (label==0)
@@ -292,18 +294,18 @@ void template_base::fill_kernel_name(char * ptr, unsigned int label, const char
*ptr++='\0'; *ptr++='\0';
} }
template_base::invalid_exception::invalid_exception() : message_() {} base::invalid_exception::invalid_exception() : message_() {}
template_base::invalid_exception::invalid_exception(std::string message) : base::invalid_exception::invalid_exception(std::string message) :
message_("ViennaCL: Internal error: The generator cannot apply the given template to the given symbolic_expression: " + message + "\n" message_("ViennaCL: Internal error: The generator cannot apply the given template to the given symbolic_expression: " + message + "\n"
"If you are using a builtin template, please report on viennacl-support@lists.sourceforge.net! We will provide a fix as soon as possible\n" "If you are using a builtin template, please report on viennacl-support@lists.sourceforge.net! We will provide a fix as soon as possible\n"
"If you are using your own template, please try using other parameters") {} "If you are using your own template, please try using other parameters") {}
const char* template_base::invalid_exception::what() const throw() { return message_.c_str(); } const char* base::invalid_exception::what() const throw() { return message_.c_str(); }
template_base::invalid_exception::~invalid_exception() throw() {} base::invalid_exception::~invalid_exception() throw() {}
void template_base::fetching_loop_info(fetching_policy_type policy, std::string const & bound, kernel_generation_stream & stream, std::string & init, std::string & upper_bound, std::string & inc, std::string const & domain_id, std::string const & domain_size) void base::fetching_loop_info(fetching_policy_type policy, std::string const & bound, kernel_generation_stream & stream, std::string & init, std::string & upper_bound, std::string & inc, std::string const & domain_id, std::string const & domain_size)
{ {
if (policy==FETCH_FROM_GLOBAL_STRIDED) if (policy==FETCH_FROM_GLOBAL_STRIDED)
{ {
@@ -326,7 +328,7 @@ void template_base::fetching_loop_info(fetching_policy_type policy, std::string
} }
} }
bool template_base::is_node_trans(symbolic_expression::container_type const & array, size_t root_idx, leaf_t leaf_type) bool base::is_node_trans(symbolic_expression::container_type const & array, size_t root_idx, leaf_t leaf_type)
{ {
bool res = false; bool res = false;
lhs_rhs_element symbolic_expression_node::*ptr; lhs_rhs_element symbolic_expression_node::*ptr;
@@ -344,7 +346,7 @@ bool template_base::is_node_trans(symbolic_expression::container_type const & ar
return res; return res;
} }
std::string template_base::append_simd_suffix(std::string const & str, unsigned int i) std::string base::append_simd_suffix(std::string const & str, unsigned int i)
{ {
assert(i < 16); assert(i < 16);
char suffixes[] = {'0','1','2','3','4','5','6','7','8','9', char suffixes[] = {'0','1','2','3','4','5','6','7','8','9',
@@ -352,15 +354,16 @@ std::string template_base::append_simd_suffix(std::string const & str, unsigned
return str + tools::to_string(suffixes[i]); return str + tools::to_string(suffixes[i]);
} }
bool template_base::is_offset_modifier(symbolic_expression_node const & node) bool base::is_strided(symbolic_expression_node const & node)
{ {
return node.op.type==OPERATOR_VECTOR_DIAG_TYPE return node.op.type==OPERATOR_VDIAG_TYPE
|| node.op.type==OPERATOR_MATRIX_DIAG_TYPE || node.op.type==OPERATOR_MATRIX_DIAG_TYPE
|| node.op.type==OPERATOR_MATRIX_ROW_TYPE || node.op.type==OPERATOR_MATRIX_ROW_TYPE
|| node.op.type==OPERATOR_MATRIX_COLUMN_TYPE; || node.op.type==OPERATOR_MATRIX_COLUMN_TYPE
|| node.op.type==OPERATOR_OUTER_PROD_TYPE;
} }
bool template_base::has_strided_access(symbolic_expressions_container const & symbolic_expressions) const bool base::has_strided_access(symbolic_expressions_container const & symbolic_expressions) const
{ {
for (symbolic_expressions_container::data_type::const_iterator it = symbolic_expressions.data().begin(); it != symbolic_expressions.data().end(); ++it) for (symbolic_expressions_container::data_type::const_iterator it = symbolic_expressions.data().begin(); it != symbolic_expressions.data().end(); ++it)
{ {
@@ -368,13 +371,13 @@ bool template_base::has_strided_access(symbolic_expressions_container const & sy
for (std::vector<lhs_rhs_element>::iterator itt = arrays.begin(); itt != arrays.end(); ++itt) for (std::vector<lhs_rhs_element>::iterator itt = arrays.begin(); itt != arrays.end(); ++itt)
if(max(itt->array->stride())>1) if(max(itt->array->stride())>1)
return true; return true;
if(filter_nodes(&is_offset_modifier, **it, true).empty()==false) if(filter_nodes(&is_strided, **it, true).empty()==false)
return true; return true;
} }
return false; return false;
} }
int_t template_base::vector_size(symbolic_expression_node const & node) int_t base::vector_size(symbolic_expression_node const & node)
{ {
using namespace tools; using namespace tools;
if (node.op.type==OPERATOR_MATRIX_DIAG_TYPE) if (node.op.type==OPERATOR_MATRIX_DIAG_TYPE)
@@ -388,20 +391,20 @@ int_t template_base::vector_size(symbolic_expression_node const & node)
} }
std::pair<int_t, int_t> template_base::matrix_size(symbolic_expression_node const & node) std::pair<int_t, int_t> base::matrix_size(symbolic_expression_node const & node)
{ {
if (node.op.type==OPERATOR_VECTOR_DIAG_TYPE) if (node.op.type==OPERATOR_VDIAG_TYPE)
{ {
int_t size = node.lhs.array->shape()._1; int_t size = node.lhs.array->shape()._1;
return std::make_pair(size,size); return std::make_pair(size,size);
} }
else if(node.op.type==OPERATOR_MATRIX_REPEAT_TYPE) else if(node.op.type==OPERATOR_REPEAT_TYPE)
return std::make_pair(node.lhs.array->shape()._1*node.rhs.repeat_infos->rep._1, node.lhs.array->shape()._2*node.rhs.repeat_infos->rep._2); return std::make_pair(node.lhs.array->shape()._1*node.rhs.tuple->rep._1, node.lhs.array->shape()._2*node.rhs.tuple->rep._2);
else else
return std::make_pair(node.lhs.array->shape()._1,node.lhs.array->shape()._2); return std::make_pair(node.lhs.array->shape()._1,node.lhs.array->shape()._2);
} }
void template_base::element_wise_loop_1D(kernel_generation_stream & stream, loop_body_base const & loop_body, void base::element_wise_loop_1D(kernel_generation_stream & stream, loop_body_base const & loop_body,
fetching_policy_type fetch, unsigned int simd_width, std::string const & i, std::string const & bound, std::string const & domain_id, std::string const & domain_size) fetching_policy_type fetch, unsigned int simd_width, std::string const & i, std::string const & bound, std::string const & domain_id, std::string const & domain_size)
{ {
std::string strwidth = tools::to_string(simd_width); std::string strwidth = tools::to_string(simd_width);
@@ -427,14 +430,14 @@ void template_base::element_wise_loop_1D(kernel_generation_stream & stream, loop
} }
} }
bool template_base::is_reduction(symbolic_expression_node const & node) bool base::is_reduction(symbolic_expression_node const & node)
{ {
return node.op.type_family==OPERATOR_VECTOR_REDUCTION_TYPE_FAMILY return node.op.type_family==OPERATOR_VECTOR_REDUCTION_TYPE_FAMILY
|| node.op.type_family==OPERATOR_COLUMNS_REDUCTION_TYPE_FAMILY || node.op.type_family==OPERATOR_COLUMNS_REDUCTION_TYPE_FAMILY
|| node.op.type_family==OPERATOR_ROWS_REDUCTION_TYPE_FAMILY; || node.op.type_family==OPERATOR_ROWS_REDUCTION_TYPE_FAMILY;
} }
bool template_base::is_index_reduction(op_element const & op) bool base::is_index_reduction(op_element const & op)
{ {
return op.type==OPERATOR_ELEMENT_ARGFMAX_TYPE return op.type==OPERATOR_ELEMENT_ARGFMAX_TYPE
|| op.type==OPERATOR_ELEMENT_ARGMAX_TYPE || op.type==OPERATOR_ELEMENT_ARGMAX_TYPE
@@ -442,7 +445,7 @@ bool template_base::is_index_reduction(op_element const & op)
|| op.type==OPERATOR_ELEMENT_ARGMIN_TYPE; || op.type==OPERATOR_ELEMENT_ARGMIN_TYPE;
} }
std::string template_base::vstore(unsigned int simd_width, std::string const & value, std::string const & offset, std::string const & ptr) std::string base::vstore(unsigned int simd_width, std::string const & value, std::string const & offset, std::string const & ptr)
{ {
if (simd_width==1) if (simd_width==1)
return "(" + ptr + ")[" + offset + "] = " + value; return "(" + ptr + ")[" + offset + "] = " + value;
@@ -450,7 +453,7 @@ std::string template_base::vstore(unsigned int simd_width, std::string const & v
return append_width("vstore", simd_width) + "(" + value + ", " + offset + ", " + ptr + ")"; return append_width("vstore", simd_width) + "(" + value + ", " + offset + ", " + ptr + ")";
} }
std::string template_base::vload(unsigned int simd_width, std::string const & offset, std::string const & ptr) std::string base::vload(unsigned int simd_width, std::string const & offset, std::string const & ptr)
{ {
if (simd_width==1) if (simd_width==1)
return "(" + ptr + ")[" + offset + "]"; return "(" + ptr + ")[" + offset + "]";
@@ -458,21 +461,21 @@ std::string template_base::vload(unsigned int simd_width, std::string const & of
return append_width("vload", simd_width) + "(" + offset + ", " + ptr + ")"; return append_width("vload", simd_width) + "(" + offset + ", " + ptr + ")";
} }
std::string template_base::append_width(std::string const & str, unsigned int width) std::string base::append_width(std::string const & str, unsigned int width)
{ {
if (width==1) if (width==1)
return str; return str;
return str + tools::to_string(width); return str + tools::to_string(width);
} }
unsigned int template_base::align(unsigned int to_round, unsigned int base) unsigned int base::align(unsigned int to_round, unsigned int base)
{ {
if (to_round % base == 0) if (to_round % base == 0)
return to_round; return to_round;
return (to_round + base - 1)/base * base; return (to_round + base - 1)/base * base;
} }
inline tools::shared_ptr<symbolic_binder> template_base::make_binder() inline tools::shared_ptr<symbolic_binder> base::make_binder()
{ {
if (binding_policy_==BIND_TO_HANDLE) if (binding_policy_==BIND_TO_HANDLE)
return tools::shared_ptr<symbolic_binder>(new bind_to_handle()); return tools::shared_ptr<symbolic_binder>(new bind_to_handle());
@@ -481,19 +484,19 @@ inline tools::shared_ptr<symbolic_binder> template_base::make_binder()
} }
template_base::template_base(binding_policy_t binding_policy) : binding_policy_(binding_policy) base::base(binding_policy_t binding_policy) : binding_policy_(binding_policy)
{} {}
unsigned int template_base::lmem_usage(symbolic_expressions_container const &) const unsigned int base::lmem_usage(symbolic_expressions_container const &) const
{ return 0; } { return 0; }
unsigned int template_base::registers_usage(symbolic_expressions_container const &) const unsigned int base::registers_usage(symbolic_expressions_container const &) const
{ return 0; } { return 0; }
template_base::~template_base() base::~base()
{ } { }
std::vector<std::string> template_base::generate(unsigned int label, symbolic_expressions_container const & symbolic_expressions, cl::Device const & device) std::vector<std::string> base::generate(unsigned int label, symbolic_expressions_container const & symbolic_expressions, cl::Device const & device)
{ {
symbolic_expressions_container::data_type::const_iterator sit; symbolic_expressions_container::data_type::const_iterator sit;
std::vector<mapping_type>::iterator mit; std::vector<mapping_type>::iterator mit;
@@ -511,11 +514,11 @@ std::vector<std::string> template_base::generate(unsigned int label, symbolic_ex
} }
template<class TType, class PType> template<class TType, class PType>
int template_base_impl<TType, PType>::check_invalid_impl(cl::Device const &, symbolic_expressions_container const &) const int base_impl<TType, PType>::check_invalid_impl(cl::Device const &, symbolic_expressions_container const &) const
{ return TEMPLATE_VALID; } { return TEMPLATE_VALID; }
template<class TType, class PType> template<class TType, class PType>
bool template_base_impl<TType, PType>::has_misaligned_offset(symbolic_expressions_container const & symbolic_expressions) bool base_impl<TType, PType>::has_misaligned_offset(symbolic_expressions_container const & symbolic_expressions)
{ {
for (symbolic_expressions_container::data_type::const_iterator it = symbolic_expressions.data().begin(); it != symbolic_expressions.data().end(); ++it) for (symbolic_expressions_container::data_type::const_iterator it = symbolic_expressions.data().begin(); it != symbolic_expressions.data().end(); ++it)
{ {
@@ -528,23 +531,23 @@ bool template_base_impl<TType, PType>::has_misaligned_offset(symbolic_expression
} }
template<class TType, class PType> template<class TType, class PType>
template_base_impl<TType, PType>::template_base_impl(parameters_type const & parameters, binding_policy_t binding_policy) : template_base(binding_policy), p_(parameters) base_impl<TType, PType>::base_impl(parameters_type const & parameters, binding_policy_t binding_policy) : base(binding_policy), p_(parameters)
{ } { }
template<class TType, class PType> template<class TType, class PType>
int_t template_base_impl<TType, PType>::local_size_0() const int_t base_impl<TType, PType>::local_size_0() const
{ return p_.local_size_0; } { return p_.local_size_0; }
template<class TType, class PType> template<class TType, class PType>
int_t template_base_impl<TType, PType>::local_size_1() const int_t base_impl<TType, PType>::local_size_1() const
{ return p_.local_size_1; } { return p_.local_size_1; }
template<class TType, class PType> template<class TType, class PType>
tools::shared_ptr<template_base> template_base_impl<TType, PType>::clone() const tools::shared_ptr<base> base_impl<TType, PType>::clone() const
{ return tools::shared_ptr<template_base>(new TType(*dynamic_cast<TType const *>(this))); } { return tools::shared_ptr<base>(new TType(*dynamic_cast<TType const *>(this))); }
template<class TType, class PType> template<class TType, class PType>
int template_base_impl<TType, PType>::check_invalid(symbolic_expressions_container const & symbolic_expressions, cl::Device const & device) const int base_impl<TType, PType>::check_invalid(symbolic_expressions_container const & symbolic_expressions, cl::Device const & device) const
{ {
//Query device informations //Query device informations
size_t lmem_available = device.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>(); size_t lmem_available = device.getInfo<CL_DEVICE_LOCAL_MEM_SIZE>();
@@ -585,10 +588,10 @@ int template_base_impl<TType, PType>::check_invalid(symbolic_expressions_contain
return check_invalid_impl(device, symbolic_expressions); return check_invalid_impl(device, symbolic_expressions);
} }
template class template_base_impl<vaxpy, vaxpy_parameters>; template class base_impl<vaxpy, vaxpy_parameters>;
template class template_base_impl<reduction, reduction_parameters>; template class base_impl<reduction, reduction_parameters>;
template class template_base_impl<maxpy, maxpy_parameters>; template class base_impl<maxpy, maxpy_parameters>;
template class template_base_impl<mreduction, mreduction_parameters>; template class base_impl<mreduction, mreduction_parameters>;
template class template_base_impl<mproduct, mproduct_parameters>; template class base_impl<mproduct, mproduct_parameters>;
} }

View File

@@ -10,7 +10,7 @@ namespace atidlas
maxpy_parameters::maxpy_parameters(unsigned int _simd_width, maxpy_parameters::maxpy_parameters(unsigned int _simd_width,
unsigned int _local_size_0, unsigned int _local_size_1, unsigned int _local_size_0, unsigned int _local_size_1,
unsigned int _num_groups_0, unsigned int _num_groups_1, unsigned int _num_groups_0, unsigned int _num_groups_1,
fetching_policy_type _fetching_policy) : template_base::parameters_type(_simd_width, _local_size_0, _local_size_1, 1), num_groups_0(_num_groups_0), num_groups_1(_num_groups_1), fetching_policy(_fetching_policy){ } fetching_policy_type _fetching_policy) : base::parameters_type(_simd_width, _local_size_0, _local_size_1, 1), num_groups_0(_num_groups_0), num_groups_1(_num_groups_1), fetching_policy(_fetching_policy){ }
@@ -34,7 +34,7 @@ std::string maxpy::generate_impl(unsigned int label, symbolic_expressions_contai
stream << "{" << std::endl; stream << "{" << std::endl;
stream.inc_tab(); stream.inc_tab();
process(stream, PARENT_NODE_TYPE, tools::make_map<std::multimap<std::string, std::string> >("scalar", "#scalartype #namereg = *#pointer;") process(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("scalar", "#scalartype #namereg = *#pointer;")
("array", "#pointer = &$VALUE{#start1, #start2};"), symbolic_expressions, mappings); ("array", "#pointer = &$VALUE{#start1, #start2};"), symbolic_expressions, mappings);
fetching_loop_info(p_.fetching_policy, "M", stream, init0, upper_bound0, inc0, "get_global_id(0)", "get_global_size(0)"); fetching_loop_info(p_.fetching_policy, "M", stream, init0, upper_bound0, inc0, "get_global_id(0)", "get_global_size(0)");
@@ -46,18 +46,22 @@ std::string maxpy::generate_impl(unsigned int label, symbolic_expressions_contai
stream << "{" << std::endl; stream << "{" << std::endl;
stream.inc_tab(); stream.inc_tab();
process(stream, PARENT_NODE_TYPE, tools::make_map<std::multimap<std::string, std::string> > process(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >
("array", append_width("#scalartype",simd_width) + " #namereg = $VALUE{i*#stride1,j*#stride2};") ("array", append_width("#scalartype",simd_width) + " #namereg = $VALUE{i*#stride1,j*#stride2};")
("vector_diag", "#scalartype #namereg = ((i + ((#diag_offset<0)?#diag_offset:0))!=(j-((#diag_offset>0)?#diag_offset:0)))?0:$VALUE{min(i*#stride1, j*#stride1)};") ("vdiag", "#scalartype #namereg = ((i + ((#diag_offset<0)?#diag_offset:0))!=(j-((#diag_offset>0)?#diag_offset:0)))?0:$VALUE{min(i*#stride1, j*#stride1)};")
("matrix_repeat", "#scalartype #namereg = $VALUE{(i%#tuplearg0)*#stride1, (j%#tuplearg1)*#stride2};"), symbolic_expressions, mappings); ("repeat", "#scalartype #namereg = $VALUE{(i%#tuplearg0)*#stride1, (j%#tuplearg1)*#stride2};")
("outer", "#scalartype #namereg = ($LVALUE{i*#stride1})*($RVALUE{j*#stride1});")
evaluate(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("array", "#namereg")
("vector_diag", "#namereg")
("matrix_repeat", "#namereg")
("scalar", "#namereg")
, symbolic_expressions, mappings); , symbolic_expressions, mappings);
process(stream, LHS_NODE_TYPE, tools::make_map<std::multimap<std::string, std::string> >("array", "$VALUE{i*#stride1,j*#stride2} = #namereg;") evaluate(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >
("array", "#namereg")
("vdiag", "#namereg")
("repeat", "#namereg")
("scalar", "#namereg")
("outer", "#namereg")
, symbolic_expressions, mappings);
process(stream, LHS_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("array", "$VALUE{i*#stride1,j*#stride2} = #namereg;")
, symbolic_expressions, mappings); , symbolic_expressions, mappings);
stream.dec_tab(); stream.dec_tab();
@@ -81,12 +85,12 @@ std::vector<std::string> maxpy::generate_impl(unsigned int label, symbolic_expre
} }
maxpy::maxpy(parameters_type const & parameters, binding_policy_t binding_policy) : maxpy::maxpy(parameters_type const & parameters, binding_policy_t binding_policy) :
template_base_impl<maxpy, maxpy_parameters>(parameters, binding_policy){ } base_impl<maxpy, maxpy_parameters>(parameters, binding_policy){ }
maxpy::maxpy(unsigned int simd, unsigned int ls1, unsigned int ls2, maxpy::maxpy(unsigned int simd, unsigned int ls1, unsigned int ls2,
unsigned int ng1, unsigned int ng2, fetching_policy_type fetch, unsigned int ng1, unsigned int ng2, fetching_policy_type fetch,
binding_policy_t bind): binding_policy_t bind):
template_base_impl<maxpy, maxpy_parameters>(maxpy_parameters(simd, ls1, ls2, ng1, ng2, fetch), bind) base_impl<maxpy, maxpy_parameters>(maxpy_parameters(simd, ls1, ls2, ng1, ng2, fetch), bind)
{} {}
std::vector<int_t> maxpy::input_sizes(symbolic_expressions_container const & symbolic_expressions) std::vector<int_t> maxpy::input_sizes(symbolic_expressions_container const & symbolic_expressions)
@@ -115,6 +119,6 @@ void maxpy::enqueue(cl::CommandQueue & queue,
queue.enqueueNDRangeKernel(kernel, cl::NullRange, grange, lrange); queue.enqueueNDRangeKernel(kernel, cl::NullRange, grange, lrange);
} }
template class template_base_impl<maxpy, maxpy_parameters>; template class base_impl<maxpy, maxpy_parameters>;
} }

View File

@@ -11,7 +11,7 @@ mproduct_parameters::mproduct_parameters(unsigned int simd_width
, int_t local_size_0, int_t KL, int_t local_size_1 , int_t local_size_0, int_t KL, int_t local_size_1
, int_t ms, int_t ks, int_t ns , int_t ms, int_t ks, int_t ns
, fetching_policy_type A_fetching_policy, fetching_policy_type B_fetching_policy , fetching_policy_type A_fetching_policy, fetching_policy_type B_fetching_policy
, int_t local_fetch_0, int_t local_fetch_1): template_base::parameters_type(simd_width, local_size_0, local_size_1, 1), , int_t local_fetch_0, int_t local_fetch_1): base::parameters_type(simd_width, local_size_0, local_size_1, 1),
kL(KL), mS(ms), kS(ks), nS(ns), A_fetching_policy(A_fetching_policy), B_fetching_policy(B_fetching_policy), kL(KL), mS(ms), kS(ks), nS(ns), A_fetching_policy(A_fetching_policy), B_fetching_policy(B_fetching_policy),
local_fetch_0(local_fetch_0), local_fetch_1(local_fetch_1), local_fetch_0(local_fetch_0), local_fetch_1(local_fetch_1),
mL(ms*local_size_0), nL(ns*local_size_1){} mL(ms*local_size_0), nL(ns*local_size_1){}
@@ -625,7 +625,7 @@ mproduct_parameters::mproduct_parameters(unsigned int simd_width
return tools::make_vector<int_t>() << M << N << K; return tools::make_vector<int_t>() << M << N << K;
} }
mproduct::mproduct(mproduct_parameters const & parameters, char A_trans, char B_trans) : template_base_impl<mproduct, mproduct_parameters>(parameters, BIND_ALL_UNIQUE), A_trans_(A_trans), B_trans_(B_trans){ } mproduct::mproduct(mproduct_parameters const & parameters, char A_trans, char B_trans) : base_impl<mproduct, mproduct_parameters>(parameters, BIND_ALL_UNIQUE), A_trans_(A_trans), B_trans_(B_trans){ }
std::vector<int_t> mproduct::input_sizes(symbolic_expressions_container const & symbolic_expressions) std::vector<int_t> mproduct::input_sizes(symbolic_expressions_container const & symbolic_expressions)
{ {

View File

@@ -10,7 +10,7 @@ namespace atidlas
mreduction_parameters::mreduction_parameters(unsigned int _simd_width, mreduction_parameters::mreduction_parameters(unsigned int _simd_width,
unsigned int _local_size_0, unsigned int _local_size_1, unsigned int _local_size_0, unsigned int _local_size_1,
unsigned int _num_groups_0, fetching_policy_type _fetch_policy): template_base::parameters_type(_simd_width, _local_size_0, _local_size_1, 1), unsigned int _num_groups_0, fetching_policy_type _fetch_policy): base::parameters_type(_simd_width, _local_size_0, _local_size_1, 1),
num_groups_0(_num_groups_0), fetch_policy(_fetch_policy) { } num_groups_0(_num_groups_0), fetch_policy(_fetch_policy) { }
@@ -42,7 +42,7 @@ std::string mreduction::generate_impl(unsigned int label, symbolic_expressions_c
stream.inc_tab(); stream.inc_tab();
process(stream, PARENT_NODE_TYPE, process(stream, PARENT_NODE_TYPE,
tools::make_map<std::multimap<std::string, std::string> >("scalar", "#scalartype #namereg = *#pointer;") tools::make_map<std::map<std::string, std::string> >("scalar", "#scalartype #namereg = *#pointer;")
("array", "#pointer += #start1 + #start2*#ld;") ("array", "#pointer += #start1 + #start2*#ld;")
("array", "#ld *= #nldstride;") ("array", "#ld *= #nldstride;")
("array", "#pointer += #start1;"), symbolic_expressions, mappings); ("array", "#pointer += #start1;"), symbolic_expressions, mappings);
@@ -74,12 +74,12 @@ std::string mreduction::generate_impl(unsigned int label, symbolic_expressions_c
for (std::vector<mapped_mreduction*>::const_iterator it = exprs.begin(); it != exprs.end(); ++it) for (std::vector<mapped_mreduction*>::const_iterator it = exprs.begin(); it != exprs.end(); ++it)
{ {
std::multimap<std::string, std::string> accessors; std::map<std::string, std::string> accessors;
accessors.insert(std::make_pair("matrix_repeat", "#scalartype #namereg = $VALUE{(r%#tuplearg0)*#stride1, (c%#tuplearg1)*#stride2};")); accessors["repeat"] = "#scalartype #namereg = $VALUE{(r%#tuplearg0)*#stride1, (c%#tuplearg1)*#stride2};";
if(reduction==REDUCE_COLUMNS) if(reduction==REDUCE_COLUMNS)
accessors.insert(std::make_pair("array", data_type + " #namereg = " + vload(simd_width, "c*#stride1", "#pointer + r*#ld")+";")); accessors["array"] = data_type + " #namereg = " + vload(simd_width, "c*#stride1", "#pointer + r*#ld")+";";
else else
accessors.insert(std::make_pair("array","#scalartype #namereg = #pointer[r*#stride1 + c*#ld];")); accessors["array"] = "#scalartype #namereg = #pointer[r*#stride1 + c*#ld];";
(*it)->process_recursive(stream, PARENT_NODE_TYPE, accessors); (*it)->process_recursive(stream, PARENT_NODE_TYPE, accessors);
} }
@@ -99,7 +99,7 @@ std::string mreduction::generate_impl(unsigned int label, symbolic_expressions_c
{ {
std::map<std::string, std::string> accessors; std::map<std::string, std::string> accessors;
accessors["array"] = str[a]; accessors["array"] = str[a];
accessors["matrix_repeat"] = "#namereg"; accessors["repeat"] = "#namereg";
accessors["scalar"] = "#namereg"; accessors["scalar"] = "#namereg";
std::string value = exprs[k]->evaluate_recursive(LHS_NODE_TYPE, accessors); std::string value = exprs[k]->evaluate_recursive(LHS_NODE_TYPE, accessors);
if (exprs[k]->is_index_reduction()) if (exprs[k]->is_index_reduction())
@@ -162,6 +162,7 @@ std::string mreduction::generate_impl(unsigned int label, symbolic_expressions_c
stream.dec_tab(); stream.dec_tab();
stream << "}" << std::endl; stream << "}" << std::endl;
return stream.str(); return stream.str();
} }
@@ -192,7 +193,7 @@ std::vector<std::string> mreduction::generate_impl(unsigned int label, symbolic_
mreduction::mreduction(mreduction::parameters_type const & parameters, mreduction::mreduction(mreduction::parameters_type const & parameters,
mreduction::reduction_type rtype, mreduction::reduction_type rtype,
binding_policy_t binding_policy) : binding_policy_t binding_policy) :
template_base_impl<mreduction, mreduction_parameters>(parameters, binding_policy), base_impl<mreduction, mreduction_parameters>(parameters, binding_policy),
reduction_type_(rtype){ } reduction_type_(rtype){ }
std::vector<int_t> mreduction::input_sizes(symbolic_expressions_container const & symbolic_expressions) std::vector<int_t> mreduction::input_sizes(symbolic_expressions_container const & symbolic_expressions)
@@ -252,7 +253,7 @@ mreduction_cols::mreduction_cols(unsigned int simd, unsigned int ls1, unsigned i
mreduction(mreduction_parameters(simd, ls1, ls2, ng, fetch), REDUCE_COLUMNS, bind) mreduction(mreduction_parameters(simd, ls1, ls2, ng, fetch), REDUCE_COLUMNS, bind)
{} {}
template class template_base_impl<mreduction, mreduction_parameters>; template class base_impl<mreduction, mreduction_parameters>;
} }

View File

@@ -10,7 +10,7 @@ namespace atidlas
reduction_parameters::reduction_parameters(unsigned int _simd_width, reduction_parameters::reduction_parameters(unsigned int _simd_width,
unsigned int _group_size, unsigned int _num_groups, unsigned int _group_size, unsigned int _num_groups,
fetching_policy_type _fetching_policy) : template_base::parameters_type(_simd_width, _group_size, 1, 2), num_groups(_num_groups), fetching_policy(_fetching_policy) fetching_policy_type _fetching_policy) : base::parameters_type(_simd_width, _group_size, 1, 2), num_groups(_num_groups), fetching_policy(_fetching_policy)
{ } { }
unsigned int reduction::lmem_usage(symbolic_expressions_container const & symbolic_expressions) const unsigned int reduction::lmem_usage(symbolic_expressions_container const & symbolic_expressions) const
@@ -91,7 +91,7 @@ std::string reduction::generate_impl(unsigned int label, char type, symbolic_exp
stream.inc_tab(); stream.inc_tab();
stream << "unsigned int lid = get_local_id(0);" << std::endl; stream << "unsigned int lid = get_local_id(0);" << std::endl;
process(stream, PARENT_NODE_TYPE, tools::make_map<std::multimap<std::string, std::string> >("scalar", "#scalartype #namereg = *#pointer;") process(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("scalar", "#scalartype #namereg = *#pointer;")
("array", "#pointer += #start1;"), symbolic_expressions, mappings); ("array", "#pointer += #start1;"), symbolic_expressions, mappings);
for (unsigned int k = 0; k < N; ++k) for (unsigned int k = 0; k < N; ++k)
@@ -120,7 +120,7 @@ std::string reduction::generate_impl(unsigned int label, char type, symbolic_exp
std::string i = (simd_width==1)?"i*#stride1":"i"; std::string i = (simd_width==1)?"i*#stride1":"i";
//Fetch vector entry //Fetch vector entry
for (std::vector<mapped_scalar_reduction*>::const_iterator it = exprs.begin(); it != exprs.end(); ++it) for (std::vector<mapped_scalar_reduction*>::const_iterator it = exprs.begin(); it != exprs.end(); ++it)
(*it)->process_recursive(stream, PARENT_NODE_TYPE, tools::make_map<std::multimap<std::string, std::string> >("array", append_width("#scalartype",simd_width) + " #namereg = " + vload(simd_width,i,"#pointer")+";") (*it)->process_recursive(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("array", append_width("#scalartype",simd_width) + " #namereg = " + vload(simd_width,i,"#pointer")+";")
("matrix_row", "#scalartype #namereg = #pointer[$OFFSET{#row*#stride1, i*#stride2}];") ("matrix_row", "#scalartype #namereg = #pointer[$OFFSET{#row*#stride1, i*#stride2}];")
("matrix_column", "#scalartype #namereg = #pointer[$OFFSET{i*#stride1,#column*#stride2}];") ("matrix_column", "#scalartype #namereg = #pointer[$OFFSET{i*#stride1,#column*#stride2}];")
("matrix_diag", "#scalartype #namereg = #pointer[#diag_offset<0?$OFFSET{(i - #diag_offset)*#stride1, i*#stride2}:$OFFSET{i*#stride1, (i + #diag_offset)*#stride2}];")); ("matrix_diag", "#scalartype #namereg = #pointer[#diag_offset<0?$OFFSET{(i - #diag_offset)*#stride1, i*#stride2}:$OFFSET{i*#stride1, (i + #diag_offset)*#stride2}];"));
@@ -263,12 +263,12 @@ std::vector<std::string> reduction::generate_impl(unsigned int label, symbolic_
} }
reduction::reduction(reduction::parameters_type const & parameters, reduction::reduction(reduction::parameters_type const & parameters,
binding_policy_t binding) : template_base_impl<reduction, reduction_parameters>(parameters, binding) binding_policy_t binding) : base_impl<reduction, reduction_parameters>(parameters, binding)
{ } { }
reduction::reduction(unsigned int simd, unsigned int ls, unsigned int ng, reduction::reduction(unsigned int simd, unsigned int ls, unsigned int ng,
fetching_policy_type fetch, binding_policy_t bind): fetching_policy_type fetch, binding_policy_t bind):
template_base_impl<reduction, reduction_parameters>(reduction_parameters(simd,ls,ng,fetch), bind) base_impl<reduction, reduction_parameters>(reduction_parameters(simd,ls,ng,fetch), bind)
{} {}
std::vector<int_t> reduction::input_sizes(symbolic_expressions_container const & symbolic_expressions) std::vector<int_t> reduction::input_sizes(symbolic_expressions_container const & symbolic_expressions)
@@ -343,6 +343,6 @@ void reduction::enqueue(cl::CommandQueue & queue,
queue.enqueueNDRangeKernel(kernels[k], cl::NullRange, grange[k], lrange[k]); queue.enqueueNDRangeKernel(kernels[k], cl::NullRange, grange[k], lrange[k]);
} }
template class template_base_impl<reduction, reduction_parameters>; template class base_impl<reduction, reduction_parameters>;
} }

View File

@@ -12,7 +12,7 @@ namespace atidlas
vaxpy_parameters::vaxpy_parameters(unsigned int _simd_width, vaxpy_parameters::vaxpy_parameters(unsigned int _simd_width,
unsigned int _group_size, unsigned int _num_groups, unsigned int _group_size, unsigned int _num_groups,
fetching_policy_type _fetching_policy) : fetching_policy_type _fetching_policy) :
template_base::parameters_type(_simd_width, _group_size, 1, 1), num_groups(_num_groups), fetching_policy(_fetching_policy) base::parameters_type(_simd_width, _group_size, 1, 1), num_groups(_num_groups), fetching_policy(_fetching_policy)
{ } { }
@@ -39,7 +39,7 @@ std::vector<std::string> vaxpy::generate_impl(unsigned int label, symbolic_expre
stream.inc_tab(); stream.inc_tab();
process(stream, PARENT_NODE_TYPE, process(stream, PARENT_NODE_TYPE,
tools::make_map<std::multimap<std::string, std::string> >("scalar", "#scalartype #namereg = *#pointer;") tools::make_map<std::map<std::string, std::string> >("scalar", "#scalartype #namereg = *#pointer;")
("array", "#pointer += #start1 + #start2*#ld;") ("array", "#pointer += #start1 + #start2*#ld;")
("array", "#start1/=" + str_simd_width + ";"), symbolic_expressions, mappings); ("array", "#start1/=" + str_simd_width + ";"), symbolic_expressions, mappings);
@@ -49,7 +49,7 @@ std::vector<std::string> vaxpy::generate_impl(unsigned int label, symbolic_expre
stream << "{" << std::endl; stream << "{" << std::endl;
stream.inc_tab(); stream.inc_tab();
process(stream, PARENT_NODE_TYPE, process(stream, PARENT_NODE_TYPE,
tools::make_map<std::multimap<std::string, std::string> >("array", data_type + " #namereg = #pointer[i*#stride1];") tools::make_map<std::map<std::string, std::string> >("array", data_type + " #namereg = #pointer[i*#stride1];")
("matrix_row", "#scalartype #namereg = $VALUE{#row*#stride1, i*#stride2};") ("matrix_row", "#scalartype #namereg = $VALUE{#row*#stride1, i*#stride2};")
("matrix_column", "#scalartype #namereg = $VALUE{i*#stride1,#column*#stride2};") ("matrix_column", "#scalartype #namereg = $VALUE{i*#stride1,#column*#stride2};")
("matrix_diag", "#scalartype #namereg = #pointer[#diag_offset<0?$OFFSET{(i - #diag_offset)*#stride1, i*#stride2}:$OFFSET{i*#stride1, (i + #diag_offset)*#stride2}];") ("matrix_diag", "#scalartype #namereg = #pointer[#diag_offset<0?$OFFSET{(i - #diag_offset)*#stride1, i*#stride2}:$OFFSET{i*#stride1, (i + #diag_offset)*#stride2}];")
@@ -61,7 +61,7 @@ std::vector<std::string> vaxpy::generate_impl(unsigned int label, symbolic_expre
("matrix_diag", "#namereg") ("matrix_diag", "#namereg")
("scalar", "#namereg"), symbolic_expressions, mappings); ("scalar", "#namereg"), symbolic_expressions, mappings);
process(stream, LHS_NODE_TYPE, tools::make_map<std::multimap<std::string, std::string> >("array", "#pointer[i*#stride1] = #namereg;") process(stream, LHS_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("array", "#pointer[i*#stride1] = #namereg;")
("matrix_row", "$VALUE{#row, i} = #namereg;") ("matrix_row", "$VALUE{#row, i} = #namereg;")
("matrix_column", "$VALUE{i, #column} = #namereg;") ("matrix_column", "$VALUE{i, #column} = #namereg;")
("matrix_diag", "#diag_offset<0?$VALUE{(i - #diag_offset)*#stride1, i*#stride2}:$VALUE{i*#stride1, (i + #diag_offset)*#stride2} = #namereg;") ("matrix_diag", "#diag_offset<0?$VALUE{(i - #diag_offset)*#stride1, i*#stride2}:$VALUE{i*#stride1, (i + #diag_offset)*#stride2} = #namereg;")
@@ -73,7 +73,7 @@ std::vector<std::string> vaxpy::generate_impl(unsigned int label, symbolic_expre
stream << "if(get_global_id(0)==0)" << std::endl; stream << "if(get_global_id(0)==0)" << std::endl;
stream << "{" << std::endl; stream << "{" << std::endl;
stream.inc_tab(); stream.inc_tab();
process(stream, LHS_NODE_TYPE, tools::make_map<std::multimap<std::string, std::string> >("scalar", "*#pointer = #namereg;"), symbolic_expressions, mappings); process(stream, LHS_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("scalar", "*#pointer = #namereg;"), symbolic_expressions, mappings);
stream.dec_tab(); stream.dec_tab();
stream << "}" << std::endl; stream << "}" << std::endl;
@@ -88,12 +88,12 @@ std::vector<std::string> vaxpy::generate_impl(unsigned int label, symbolic_expre
vaxpy::vaxpy(vaxpy_parameters const & parameters, vaxpy::vaxpy(vaxpy_parameters const & parameters,
binding_policy_t binding_policy) : binding_policy_t binding_policy) :
template_base_impl<vaxpy, vaxpy_parameters>(parameters, binding_policy) base_impl<vaxpy, vaxpy_parameters>(parameters, binding_policy)
{} {}
vaxpy::vaxpy(unsigned int simd, unsigned int ls, unsigned int ng, vaxpy::vaxpy(unsigned int simd, unsigned int ls, unsigned int ng,
fetching_policy_type fetch, binding_policy_t bind): fetching_policy_type fetch, binding_policy_t bind):
template_base_impl<vaxpy, vaxpy_parameters>(vaxpy_parameters(simd,ls,ng,fetch), bind) base_impl<vaxpy, vaxpy_parameters>(vaxpy_parameters(simd,ls,ng,fetch), bind)
{} {}

View File

@@ -64,12 +64,15 @@ cl::Program program_map::add(cl::Context & context, std::string const & pname, s
res = cl::Program(context, cl::Program::Sources(1, std::make_pair(csrc, srclen))); res = cl::Program(context, cl::Program::Sources(1, std::make_pair(csrc, srclen)));
} }
try{
err = res.build(devices); err = res.build(devices);
}catch(cl::Error const & e){
if (err != CL_SUCCESS) if (err != CL_SUCCESS)
for(std::vector< cl::Device >::const_iterator it = devices.begin(); it != devices.end(); ++it) for(std::vector< cl::Device >::const_iterator it = devices.begin(); it != devices.end(); ++it)
std::cout << "Device : " << it->getInfo<CL_DEVICE_NAME>() std::cout << "Device : " << it->getInfo<CL_DEVICE_NAME>()
<< "Build Status = " << res.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(*it) << std::endl << "Build Status = " << res.getBuildInfo<CL_PROGRAM_BUILD_STATUS>(*it) << std::endl
<< "Build Log = " << res.getBuildInfo<CL_PROGRAM_BUILD_LOG>(*it) << std::endl; << "Build Log = " << res.getBuildInfo<CL_PROGRAM_BUILD_LOG>(*it) << std::endl;
}
// Store the program in the cache // Store the program in the cache

View File

@@ -69,14 +69,14 @@ std::vector<cl::lazy_compiler>& model::init(symbolic_expressions_container const
return to_init; return to_init;
} }
model::model(predictors::random_forest const & predictor, std::vector< tools::shared_ptr<template_base> > const & templates, cl::CommandQueue & queue) : model::model(predictors::random_forest const & predictor, std::vector< tools::shared_ptr<base> > const & templates, cl::CommandQueue & queue) :
templates_(templates), predictor_(new predictors::random_forest(predictor)), queue_(queue) templates_(templates), predictor_(new predictors::random_forest(predictor)), queue_(queue)
{} {}
model::model(std::vector< tools::shared_ptr<template_base> > const & templates, cl::CommandQueue & queue) : templates_(templates), queue_(queue) model::model(std::vector< tools::shared_ptr<base> > const & templates, cl::CommandQueue & queue) : templates_(templates), queue_(queue)
{} {}
model::model(template_base const & tp, cl::CommandQueue & queue) : templates_(1,tp.clone()), queue_(queue) model::model(base const & tp, cl::CommandQueue & queue) : templates_(1,tp.clone()), queue_(queue)
{} {}
void model::execute(symbolic_expressions_container const & symbolic_expressions, bool bypass_predictor, bool force_recompilation) void model::execute(symbolic_expressions_container const & symbolic_expressions, bool bypass_predictor, bool force_recompilation)
@@ -160,24 +160,24 @@ namespace detail
throw "Unsupported operation"; throw "Unsupported operation";
} }
static tools::shared_ptr<template_base> create(std::string const & template_name, std::vector<int> const & a) static tools::shared_ptr<base> create(std::string const & template_name, std::vector<int> const & a)
{ {
fetching_policy_type fetch[] = {FETCH_FROM_LOCAL, FETCH_FROM_GLOBAL_STRIDED, FETCH_FROM_GLOBAL_CONTIGUOUS}; fetching_policy_type fetch[] = {FETCH_FROM_LOCAL, FETCH_FROM_GLOBAL_STRIDED, FETCH_FROM_GLOBAL_CONTIGUOUS};
if(template_name=="vector-axpy") if(template_name=="vector-axpy")
return tools::shared_ptr<template_base>(new vaxpy( vaxpy_parameters(a[0], a[1], a[2], fetch[a[3]]))); return tools::shared_ptr<base>(new vaxpy( vaxpy_parameters(a[0], a[1], a[2], fetch[a[3]])));
else if(template_name=="reduction") else if(template_name=="reduction")
return tools::shared_ptr<template_base>(new reduction( reduction_parameters(a[0], a[1], a[2], fetch[a[3]]))); return tools::shared_ptr<base>(new reduction( reduction_parameters(a[0], a[1], a[2], fetch[a[3]])));
else if(template_name=="matrix-axpy") else if(template_name=="matrix-axpy")
return tools::shared_ptr<template_base>(new maxpy( maxpy_parameters(a[0], a[1], a[2], a[3], a[4], fetch[a[5]]))); return tools::shared_ptr<base>(new maxpy( maxpy_parameters(a[0], a[1], a[2], a[3], a[4], fetch[a[5]])));
else if(template_name.find("row-wise-reduction")!=std::string::npos) else if(template_name.find("row-wise-reduction")!=std::string::npos)
{ {
return tools::shared_ptr<template_base>(new mreduction_rows( mreduction_parameters(a[0], a[1], a[2], a[3], fetch[a[4]]))); return tools::shared_ptr<base>(new mreduction_rows( mreduction_parameters(a[0], a[1], a[2], a[3], fetch[a[4]])));
} }
else if(template_name.find("matrix-product")!=std::string::npos) else if(template_name.find("matrix-product")!=std::string::npos)
{ {
char A_trans = template_name[15]; char A_trans = template_name[15];
char B_trans = template_name[16]; char B_trans = template_name[16];
return tools::shared_ptr<template_base>(new mproduct( mproduct_parameters(a[0], a[1], a[2], a[3], a[4], a[5], a[6], return tools::shared_ptr<base>(new mproduct( mproduct_parameters(a[0], a[1], a[2], a[3], a[4], a[5], a[6],
fetch[a[7]], fetch[a[8]], a[9], a[10]), A_trans, B_trans)); fetch[a[7]], fetch[a[8]], a[9], a[10]), A_trans, B_trans));
} }
else else
@@ -217,7 +217,7 @@ model_map_t import(std::string const & fname, cl::CommandQueue & queue)
numeric_type dtype = detail::get_dtype(*dt); numeric_type dtype = detail::get_dtype(*dt);
// Get profiles // Get profiles
std::vector<tools::shared_ptr<template_base> > templates; std::vector<tools::shared_ptr<base> > templates;
js::Value const & profiles = document[opcstr][dtcstr]["profiles"]; js::Value const & profiles = document[opcstr][dtcstr]["profiles"];
for (js::SizeType id = 0 ; id < profiles.Size() ; ++id) for (js::SizeType id = 0 ; id < profiles.Size() ; ++id)
templates.push_back(detail::create(*op, tools::to_int_array<int>(profiles[id]))); templates.push_back(detail::create(*op, tools::to_int_array<int>(profiles[id])));

View File

@@ -39,12 +39,12 @@ lhs_rhs_element::lhs_rhs_element(atidlas::value_scalar const & x)
vscalar = x.values(); vscalar = x.values();
} }
lhs_rhs_element::lhs_rhs_element(atidlas::array_repeat_infos const & x) lhs_rhs_element::lhs_rhs_element(atidlas::repeat_infos const & x)
{ {
type_family = INFOS_TYPE_FAMILY; type_family = INFOS_TYPE_FAMILY;
subtype = MATRIX_REPEAT_INFOS_TYPE; subtype = REPEAT_INFOS_TYPE;
dtype = INVALID_NUMERIC_TYPE; dtype = INVALID_NUMERIC_TYPE;
repeat_infos = (atidlas::array_repeat_infos*)&x; tuple = (atidlas::repeat_infos*)&x;
} }
// //

View File

@@ -60,7 +60,7 @@ namespace detail
} }
} }
inline std::string express(atidlas::symbolic_expression const & s) std::string to_string(atidlas::symbolic_expression const & s)
{ {
std::ostringstream os; std::ostringstream os;
detail::print_node(os, s, s.root()); detail::print_node(os, s, s.root());

View File

@@ -530,7 +530,7 @@ void export_scalar()
void export_model() void export_model()
{ {
bp::class_<atidlas::model>("model", bp::init<atd::template_base const &, atd::cl::CommandQueue&>()) bp::class_<atidlas::model>("model", bp::init<atd::base const &, atd::cl::CommandQueue&>())
.def("execute", &atd::model::execute); .def("execute", &atd::model::execute);
bp::enum_<atidlas::fetching_policy_type> bp::enum_<atidlas::fetching_policy_type>
@@ -542,17 +542,17 @@ void export_model()
//Base //Base
{ {
#define __PROP(name) .def_readonly(#name, &atidlas::template_base::parameters_type::name) #define __PROP(name) .def_readonly(#name, &atidlas::base::parameters_type::name)
bp::class_<atidlas::template_base, boost::noncopyable>("template_base", bp::no_init) bp::class_<atidlas::base, boost::noncopyable>("base", bp::no_init)
.def("lmem_usage", &atidlas::template_base::lmem_usage) .def("lmem_usage", &atidlas::base::lmem_usage)
.def("registers_usage", &atidlas::template_base::registers_usage) .def("registers_usage", &atidlas::base::registers_usage)
.def("check_invalid", &atidlas::template_base::check_invalid) .def("check_invalid", &atidlas::base::check_invalid)
; ;
#undef __PROP #undef __PROP
} }
#define WRAP_TEMPLATE(name, ...) bp::class_<atidlas::template_base_impl<atidlas::name, atidlas::name::parameters_type>, bp::bases<atidlas::template_base>, boost::noncopyable>(#name "_base_impl", bp::no_init);\ #define WRAP_TEMPLATE(name, ...) bp::class_<atidlas::base_impl<atidlas::name, atidlas::name::parameters_type>, bp::bases<atidlas::base>, boost::noncopyable>(#name "_base_impl", bp::no_init);\
bp::class_<atidlas::name, bp::bases<atidlas::template_base_impl<atidlas::name, atidlas::name::parameters_type> > >(#name, bp::init<__VA_ARGS__>())\ bp::class_<atidlas::name, bp::bases<atidlas::base_impl<atidlas::name, atidlas::name::parameters_type> > >(#name, bp::init<__VA_ARGS__>())\
.add_property("local_size_0", &atd::name::local_size_0)\ .add_property("local_size_0", &atd::name::local_size_0)\
.add_property("local_size_1", &atd::name::local_size_1); .add_property("local_size_1", &atd::name::local_size_1);

View File

@@ -161,23 +161,23 @@ bool failure_vector(VecType1 const & x, VecType2 const & y, typename VecType1::v
#define INIT_VECTOR(N, SUBN, START, STRIDE, CPREFIX, PREFIX) \ #define INIT_VECTOR(N, SUBN, START, STRIDE, CPREFIX, PREFIX) \
simple_vector<T> CPREFIX ## _vector(N);\ simple_vector<T> CPREFIX ## _full(N);\
simple_vector_slice<T> CPREFIX ## _slice(CPREFIX ## _vector, START, START + STRIDE*SUBN, STRIDE);\ simple_vector_slice<T> CPREFIX ## _slice(CPREFIX ## _full, START, START + STRIDE*SUBN, STRIDE);\
init_rand(CPREFIX ## _vector);\ init_rand(CPREFIX ## _full);\
atidlas::array PREFIX ## _vector(CPREFIX ## _vector.data());\ atidlas::array PREFIX ## _full(CPREFIX ## _full.data());\
atidlas::array PREFIX ## _slice = PREFIX ## _vector[atidlas::_(START, START + STRIDE*SUBN, STRIDE)]; atidlas::array PREFIX ## _slice = PREFIX ## _full[atidlas::_(START, START + STRIDE*SUBN, STRIDE)];
#define INIT_MATRIX(M, SUBM, START1, STRIDE1, N, SUBN, START2, STRIDE2, CPREFIX, PREFIX) \ #define INIT_MATRIX(M, SUBM, START1, STRIDE1, N, SUBN, START2, STRIDE2, CPREFIX, PREFIX) \
simple_matrix<T> CPREFIX ## _matrix(M, N);\ simple_matrix<T> CPREFIX ## _full(M, N);\
simple_matrix_slice<T> CPREFIX ## _slice(CPREFIX ## _matrix, START1, START1 + STRIDE1*SUBM, STRIDE1,\ simple_matrix_slice<T> CPREFIX ## _slice(CPREFIX ## _full, START1, START1 + STRIDE1*SUBM, STRIDE1,\
START2, START2 + STRIDE2*SUBN, STRIDE2);\ START2, START2 + STRIDE2*SUBN, STRIDE2);\
init_rand(CPREFIX ## _matrix);\ init_rand(CPREFIX ## _full);\
atidlas::array PREFIX ## _matrix(M, N, CPREFIX ## _matrix.data());\ atidlas::array PREFIX ## _full(M, N, CPREFIX ## _full.data());\
atidlas::array PREFIX ## _slice(PREFIX ## _matrix(atidlas::_(START1, START1 + STRIDE1*SUBM, STRIDE1),\ atidlas::array PREFIX ## _slice(PREFIX ## _full(atidlas::_(START1, START1 + STRIDE1*SUBM, STRIDE1),\
atidlas::_(START2, START2 + STRIDE2*SUBN, STRIDE2)));\ atidlas::_(START2, START2 + STRIDE2*SUBN, STRIDE2)));\
simple_matrix<T> CPREFIX ## T_matrix = simple_trans(CPREFIX ## _matrix);\ simple_matrix<T> CPREFIX ## T_full = simple_trans(CPREFIX ## _full);\
atidlas::array PREFIX ## T_matrix(N, M, CPREFIX ## T_matrix.data());\ atidlas::array PREFIX ## T_full(N, M, CPREFIX ## T_full.data());\
atidlas::array PREFIX ## T_slice(PREFIX ## T_matrix(atidlas::_(START2, START2 + STRIDE2*SUBN, STRIDE2),\ atidlas::array PREFIX ## T_slice(PREFIX ## T_full(atidlas::_(START2, START2 + STRIDE2*SUBN, STRIDE2),\
atidlas::_(START1, START1 + STRIDE1*SUBM, STRIDE1)));\ atidlas::_(START1, START1 + STRIDE1*SUBM, STRIDE1)));\

View File

@@ -7,8 +7,8 @@ namespace ad = atidlas;
typedef atidlas::int_t int_t; typedef atidlas::int_t int_t;
template<typename T> template<typename T>
void test(T epsilon, simple_matrix_base<T> & cA, simple_matrix_base<T>& cB, simple_matrix_base<T>& cC, void test(T epsilon, simple_matrix_base<T> & cA, simple_matrix_base<T>& cB, simple_matrix_base<T>& cC, simple_vector_base<T>& cx, simple_vector_base<T>& cy,
ad::array& A, ad::array& B, ad::array& C) ad::array& A, ad::array& B, ad::array& C, ad::array& x, ad::array& y)
{ {
using namespace std; using namespace std;
@@ -83,6 +83,8 @@ void test(T epsilon, simple_matrix_base<T> & cA, simple_matrix_base<T>& cB, simp
RUN_TEST("C = pow(A,B)", cC(i,j) = pow(cA(i,j), cB(i,j)), C= pow(A,B)) RUN_TEST("C = pow(A,B)", cC(i,j) = pow(cA(i,j), cB(i,j)), C= pow(A,B))
RUN_TEST("C = eye(M, N)", cC(i,j) = i==j, C= eye(M, N, C.dtype())) RUN_TEST("C = eye(M, N)", cC(i,j) = i==j, C= eye(M, N, C.dtype()))
RUN_TEST("C = outer(x, y)", cC(i,j) = cx[i]*cy[j], C= outer(x,y))
#undef RUN_TEST #undef RUN_TEST
if(failure_count > 0) if(failure_count > 0)
@@ -102,14 +104,15 @@ void test_impl(T epsilon)
INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cA, A); INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cA, A);
INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cB, B); INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cB, B);
INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cC, C); INIT_MATRIX(M, SUBM, 5, 3, N, SUBN, 7, 2, cC, C);
INIT_VECTOR(M, SUBM, 5, 3, cx, x);
#define TEST_OPERATIONS(XTYPE, YTYPE, ZTYPE)\ INIT_VECTOR(N, SUBN, 7, 2, cy, y);
test(epsilon, cA_ ## XTYPE, cB_ ## YTYPE, cC_ ## ZTYPE, A_ ## XTYPE, B_ ## YTYPE, C_ ## ZTYPE);\ #define TEST_OPERATIONS(TYPE)\
test(epsilon, cA_ ## TYPE, cB_ ## TYPE, cC_ ## TYPE, cx_ ## TYPE, cy_ ## TYPE, A_ ## TYPE, B_ ## TYPE, C_ ## TYPE, x_ ## TYPE, y_ ## TYPE);\
std::cout << "> standard..." << std::endl; std::cout << "> standard..." << std::endl;
TEST_OPERATIONS(matrix, matrix, matrix); TEST_OPERATIONS(full);
std::cout << "> slice..." << std::endl; std::cout << "> slice..." << std::endl;
TEST_OPERATIONS(slice, slice, slice); TEST_OPERATIONS(slice);
} }
int main() int main()