ViennaCL - The Vienna Computing Library
1.5.2
|
00001 #ifndef VIENNACL_GENERATOR_MAPPED_TYPE_HPP 00002 #define VIENNACL_GENERATOR_MAPPED_TYPE_HPP 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2014, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 Portions of this software are copyright by UChicago Argonne, LLC. 00009 00010 ----------------- 00011 ViennaCL - The Vienna Computing Library 00012 ----------------- 00013 00014 Project Head: Karl Rupp rupp@iue.tuwien.ac.at 00015 00016 (A list of authors and contributors can be found in the PDF manual) 00017 00018 License: MIT (X11), see file LICENSE in the base directory 00019 ============================================================================= */ 00020 00021 00026 #include <string> 00027 00028 #include "viennacl/scheduler/forwards.h" 00029 #include "viennacl/generator/forwards.h" 00030 #include "viennacl/generator/utils.hpp" 00031 00032 namespace viennacl{ 00033 00034 namespace generator{ 00035 00036 namespace detail{ 00037 00038 00041 class mapped_object{ 00042 protected: 00044 struct node_info{ 00045 node_info() : mapping(NULL), statement(NULL), root_node(NULL) { } 00046 mapping_type const * mapping; 00047 scheduler::statement const * statement; 00048 scheduler::statement_node const * root_node; 00049 }; 00051 virtual std::string generate_default(std::pair<std::string, std::string> const & index) const = 0; 00052 virtual std::string append_vector_size(std::string const & scalartype, unsigned int) const { return scalartype; } 00053 00054 public: 00055 mapped_object(std::string const & scalartype) : scalartype_(scalartype){ } 00056 virtual std::string & append_kernel_arguments(std::set<std::string> &, std::string & str, unsigned int) const{ return str; } 00057 std::string const & scalartype() const { return scalartype_; } 00058 void access_name(std::string const & str) { access_name_ = str; } 00059 std::string const & access_name() const { return access_name_; } 00060 virtual std::string generate(std::pair<std::string, std::string> const & index, int) const{ 00061 if(!access_name_.empty()) 00062 return access_name_; 00063 else 00064 return generate_default(index); 00065 } 00066 virtual ~mapped_object(){ } 00067 protected: 00068 std::string access_name_; 00069 std::string scalartype_; 00070 }; 00071 00074 class mapped_binary_leaf : public mapped_object{ 00075 public: 00076 mapped_binary_leaf(std::string const & scalartype) : mapped_object(scalartype){ } 00077 mapping_type const & mapping() const { return *info_.mapping; } 00078 scheduler::statement const & statement() const { return *info_.statement; } 00079 scheduler::statement_node const & root_node() const { return *info_.root_node; } 00080 std::string generate_default(std::pair<std::string, std::string> const &) const { return "";} 00081 protected: 00082 node_info info_; 00083 }; 00084 00086 class mapped_matrix_product : public mapped_binary_leaf{ 00087 friend class map_functor; 00088 public: 00089 mapped_matrix_product(std::string const & scalartype) : mapped_binary_leaf(scalartype){ } 00090 }; 00091 00093 class mapped_reduction : public mapped_binary_leaf{ 00094 public: 00095 mapped_reduction(std::string const & scalartype) : mapped_binary_leaf(scalartype){ } 00096 viennacl::scheduler::operation_node_type reduction_type() const { return reduction_type_; } 00097 private: 00098 viennacl::scheduler::operation_node_type reduction_type_; 00099 }; 00100 00102 class mapped_scalar_reduction : public mapped_reduction{ 00103 friend class map_functor; 00104 public: 00105 mapped_scalar_reduction(std::string const & scalartype) : mapped_reduction(scalartype){ } 00106 }; 00107 00109 class mapped_vector_reduction : public mapped_reduction{ 00110 friend class map_functor; 00111 public: 00112 mapped_vector_reduction(std::string const & scalartype) : mapped_reduction(scalartype){ } 00113 }; 00114 00116 class mapped_host_scalar : public mapped_object{ 00117 friend class map_functor; 00118 std::string generate_default(std::pair<std::string, std::string> const &) const{ return name_; } 00119 public: 00120 mapped_host_scalar(std::string const & scalartype) : mapped_object(scalartype){ } 00121 std::string const & name() { return name_; } 00122 std::string & append_kernel_arguments(std::set<std::string> & already_generated, std::string & str, unsigned int) const{ 00123 if(already_generated.insert(name_).second) 00124 str += detail::generate_value_kernel_argument(scalartype_, name_); 00125 return str; 00126 } 00127 00128 private: 00129 std::string name_; 00130 }; 00131 00133 class mapped_handle : public mapped_object{ 00134 virtual std::string offset(std::pair<std::string, std::string> const & index) const = 0; 00135 virtual void append_optional_arguments(std::string &) const{ } 00136 std::string generate_default(std::pair<std::string, std::string> const & index) const{ return name_ + '[' + offset(index) + ']'; } 00137 public: 00138 mapped_handle(std::string const & scalartype) : mapped_object(scalartype){ } 00139 00140 std::string const & name() const { return name_; } 00141 00142 void fetch(std::pair<std::string, std::string> const & index, unsigned int vectorization, std::set<std::string> & fetched, utils::kernel_generation_stream & stream) { 00143 std::string new_access_name = name_ + "_private"; 00144 if(fetched.find(name_)==fetched.end()){ 00145 stream << scalartype_; 00146 if(vectorization > 1) stream << vectorization; 00147 stream << " " << new_access_name << " = " << generate_default(index) << ';' << std::endl; 00148 fetched.insert(name_); 00149 } 00150 access_name_ = new_access_name; 00151 } 00152 00153 void write_back(std::pair<std::string, std::string> const & index, std::set<std::string> & fetched, utils::kernel_generation_stream & stream) { 00154 std::string old_access_name = access_name_ ; 00155 access_name_ = ""; 00156 if(fetched.find(name_)!=fetched.end()){ 00157 stream << generate_default(index) << " = " << old_access_name << ';' << std::endl; 00158 fetched.erase(name_); 00159 } 00160 } 00161 00162 std::string & append_kernel_arguments(std::set<std::string> & already_generated, std::string & str, unsigned int vector_size) const{ 00163 if(already_generated.insert(name_).second){ 00164 std::string vector_scalartype = append_vector_size(scalartype_, vector_size); 00165 str += detail::generate_pointer_kernel_argument("__global", vector_scalartype, name_); 00166 append_optional_arguments(str); 00167 } 00168 return str; 00169 } 00170 00171 protected: 00172 std::string name_; 00173 }; 00174 00176 class mapped_scalar : public mapped_handle{ 00177 friend class map_functor; 00178 private: 00179 std::string offset(std::pair<std::string, std::string> const &) const { return "0"; } 00180 public: 00181 mapped_scalar(std::string const & scalartype) : mapped_handle(scalartype){ } 00182 }; 00183 00184 00186 class mapped_buffer : public mapped_handle{ 00187 protected: 00188 std::string append_vector_size(std::string const & scalartype, unsigned int vector_size) const { 00189 if(vector_size>1) 00190 return scalartype + utils::to_string(vector_size); 00191 else 00192 return scalartype; 00193 } 00194 public: 00195 mapped_buffer(std::string const & scalartype) : mapped_handle(scalartype){ } 00196 virtual std::string generate(std::pair<std::string, std::string> const & index, int vector_element) const{ 00197 if(vector_element>-1) 00198 return mapped_object::generate(index, vector_element)+".s"+utils::to_string(vector_element); 00199 return mapped_object::generate(index, vector_element); 00200 } 00201 00202 }; 00203 00205 class mapped_vector : public mapped_buffer{ 00206 friend class map_functor; 00207 std::string offset(std::pair<std::string, std::string> const & index) const { 00208 if(info_.statement){ 00209 std::string str; 00210 detail::generate_all_rhs(*info_.statement, *info_.root_node, index, -1, str, *info_.mapping); 00211 return str; 00212 } 00213 else 00214 return index.first; 00215 } 00216 00217 void append_optional_arguments(std::string & str) const{ 00218 if(!start_name_.empty()) 00219 str += detail::generate_value_kernel_argument("unsigned int", start_name_); 00220 if(!stride_name_.empty()) 00221 str += detail::generate_value_kernel_argument("unsigned int", stride_name_); 00222 if(!shift_name_.empty()) 00223 str += detail::generate_value_kernel_argument("unsigned int", shift_name_); 00224 } 00225 public: 00226 mapped_vector(std::string const & scalartype) : mapped_buffer(scalartype){ } 00227 private: 00228 node_info info_; 00229 00230 std::string start_name_; 00231 std::string stride_name_; 00232 std::string shift_name_; 00233 }; 00234 00236 class mapped_matrix : public mapped_buffer{ 00237 friend class map_functor; 00238 void append_optional_arguments(std::string & str) const{ 00239 if(!start1_name_.empty()) 00240 str += detail::generate_value_kernel_argument("unsigned int", start1_name_); 00241 if(!stride1_name_.empty()) 00242 str += detail::generate_value_kernel_argument("unsigned int", stride1_name_); 00243 if(!start2_name_.empty()) 00244 str += detail::generate_value_kernel_argument("unsigned int", start2_name_); 00245 if(!stride2_name_.empty()) 00246 str += detail::generate_value_kernel_argument("unsigned int", stride2_name_); 00247 } 00248 public: 00249 mapped_matrix(std::string const & scalartype) : mapped_buffer(scalartype){ } 00250 00251 bool is_row_major() const { return is_row_major_; } 00252 00253 std::string const & size1() const { return size1_; } 00254 00255 std::string const & size2() const { return size2_; } 00256 00257 void bind_sizes(std::string const & size1, std::string const & size2) const{ 00258 size1_ = size1; 00259 size2_ = size2; 00260 } 00261 00262 std::string offset(std::pair<std::string, std::string> const & index) const { 00263 std::string i = index.first; 00264 std::string j = index.second; 00265 if(is_row_major_) 00266 if(j=="0") 00267 return '(' + i + ')' + '*' + size2_; 00268 else 00269 return '(' + i + ')' + '*' + size2_ + "+ (" + j + ')'; 00270 else 00271 if(i=="0") 00272 return "(" + j + ')' + '*' + size1_; 00273 else 00274 return '(' + i + ')' + "+ (" + j + ')' + '*' + size1_; 00275 } 00276 00277 private: 00278 mutable std::string size1_; 00279 mutable std::string size2_; 00280 00281 std::string start1_name_; 00282 std::string stride1_name_; 00283 std::string shift1_name_; 00284 std::string start2_name_; 00285 std::string stride2_name_; 00286 std::string shift2_name_; 00287 bool is_row_major_; 00288 }; 00289 00291 class mapped_implicit_vector : public mapped_object{ 00292 friend class map_functor; 00293 std::string value_name_; 00294 std::string index_name_; 00295 public: 00296 mapped_implicit_vector(std::string const & scalartype) : mapped_object(scalartype){ } 00297 std::string generate_default(std::pair<std::string, std::string> const & /*index*/) const{ 00298 return value_name_; 00299 } 00300 std::string & append_kernel_arguments(std::set<std::string> & /*already_generated*/, std::string & str, unsigned int /*vector_size*/) const{ 00301 if(!value_name_.empty()) 00302 str += detail::generate_value_kernel_argument(scalartype_, value_name_); 00303 if(!index_name_.empty()) 00304 str += detail::generate_value_kernel_argument("unsigned int", index_name_); 00305 return str; 00306 } 00307 }; 00308 00310 class mapped_implicit_matrix : public mapped_object{ 00311 friend class map_functor; 00312 std::string value_name_; 00313 public: 00314 mapped_implicit_matrix(std::string const & scalartype) : mapped_object(scalartype){ } 00315 std::string generate_default(std::pair<std::string, std::string> const & /* index */) const{ 00316 return value_name_; 00317 } 00318 std::string & append_kernel_arguments(std::set<std::string> & /*already generated*/, std::string & str, unsigned int /*vector size*/) const{ 00319 if(!value_name_.empty()) 00320 str += detail::generate_value_kernel_argument(scalartype_, value_name_); 00321 return str; 00322 } 00323 }; 00324 00325 inline std::string generate(std::pair<std::string, std::string> const & index, int vector_element, mapped_object const & s){ 00326 return s.generate(index, vector_element); 00327 } 00328 00329 static void fetch(std::pair<std::string, std::string> const & index, unsigned int vectorization, std::set<std::string> & fetched, utils::kernel_generation_stream & stream, mapped_object & s){ 00330 if(mapped_handle * p = dynamic_cast<mapped_handle *>(&s)) 00331 p->fetch(index, vectorization, fetched, stream); 00332 } 00333 00334 static std::string & append_kernel_arguments(std::set<std::string> & already_generated, std::string & str, unsigned int vector_size, mapped_object const & s){ 00335 return s.append_kernel_arguments(already_generated, str, vector_size); 00336 } 00337 00338 } 00339 00340 } 00341 00342 } 00343 #endif