|
ViennaCL - The Vienna Computing Library
1.4.2
|
00001 #ifndef VIENNACL_IO_KERNEL_PARAMETERS_HPP 00002 #define VIENNACL_IO_KERNEL_PARAMETERS_HPP 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2013, 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 "viennacl/ocl/backend.hpp" 00027 #include "pugixml/src/pugixml.hpp" 00028 00029 namespace viennacl 00030 { 00031 namespace io 00032 { 00033 namespace tag 00034 { 00035 static std::string root = "parameters"; 00036 static std::string devices = "devices"; 00037 static std::string device = "device"; 00038 static std::string name = "name"; 00039 static std::string driver = "driver"; 00040 static std::string compun = "computeunits"; 00041 static std::string workgrp = "workgroupsize"; 00042 static std::string tests = "tests"; 00043 static std::string test = "test"; 00044 static std::string numeric = "numeric"; 00045 static std::string kernels = "kernels"; 00046 static std::string kernel = "kernel"; 00047 static std::string params = "params"; 00048 static std::string param = "param"; 00049 static std::string value = "value"; 00050 static std::string alignment = "alignment"; 00051 } // end namespace tag 00052 00053 namespace val { 00054 static std::string globsize = "globalsize"; 00055 static std::string locsize = "localsize"; 00056 static std::string vec = "vector"; 00057 static std::string matrix = "matrix"; 00058 static std::string compmat = "compressed_matrix"; 00059 static std::string fl = "float"; 00060 static std::string dbl = "double"; 00061 } 00062 00064 struct parameter_database 00065 { 00066 parameter_database () 00067 { 00068 root = doc.append_child(); 00069 root.set_name(tag::root.c_str()); 00070 last = root; 00071 00072 devices_open = false; 00073 tests_open = false; 00074 kernels_open = false; 00075 parameters_open = false; 00076 } 00077 00078 void add_device() 00079 { 00080 pugi::xml_node dev; 00081 if(devices_open) 00082 { 00083 dev = devices.append_child(); 00084 dev.set_name(tag::device.c_str()); 00085 } 00086 else 00087 { 00088 devices = last.append_child(); 00089 devices.set_name(tag::devices.c_str()); 00090 00091 dev = devices.append_child(); 00092 dev.set_name(tag::device.c_str()); 00093 00094 devices_open = true; 00095 } 00096 last = dev; 00097 } 00098 00099 void add_test() 00100 { 00101 pugi::xml_node test; 00102 if(tests_open) 00103 { 00104 test = tests.append_child(); 00105 test.set_name(tag::test.c_str()); 00106 } 00107 else 00108 { 00109 tests = last.append_child(); 00110 tests.set_name(tag::tests.c_str()); 00111 00112 test = tests.append_child(); 00113 test.set_name(tag::test.c_str()); 00114 00115 tests_open = true; 00116 } 00117 last = test; 00118 // close the current kernels section 00119 // so a new one is created for this new test 00120 kernels_open = false; 00121 } 00122 00123 void add_kernel() 00124 { 00125 pugi::xml_node kern; 00126 if(kernels_open) 00127 { 00128 kern = kernels.append_child(); 00129 kern.set_name(tag::kernel.c_str()); 00130 } 00131 else 00132 { 00133 kernels = last.append_child(); 00134 kernels.set_name(tag::kernels.c_str()); 00135 00136 kern = kernels.append_child(); 00137 kern.set_name(tag::kernel.c_str()); 00138 00139 kernels_open = true; 00140 } 00141 last = kern; 00142 00143 // close the current parameters section 00144 // so a new one is created for this new kernel 00145 parameters_open = false; 00146 } 00147 00148 void add_parameter() 00149 { 00150 pugi::xml_node para; 00151 00152 if(parameters_open) 00153 { 00154 para = parameters.append_child(); 00155 para.set_name(tag::param.c_str()); 00156 } 00157 else 00158 { 00159 parameters = last.append_child(); 00160 parameters.set_name(tag::params.c_str()); 00161 00162 para = parameters.append_child(); 00163 para.set_name(tag::param.c_str()); 00164 00165 parameters_open = true; 00166 } 00167 last = para; 00168 } 00169 00170 template<typename ValueT> 00171 void add_data_node(std::string tagstr, ValueT data) 00172 { 00173 std::stringstream ss; 00174 ss << data; 00175 add_data_node(tagstr, ss.str()); 00176 } 00177 00178 void add_data_node(std::string tagstr, std::string data) 00179 { 00180 pugi::xml_node node = last.append_child(); 00181 00182 if(tagstr == tag::name) 00183 node.set_name(tag::name.c_str()); 00184 else if(tagstr == tag::driver) 00185 node.set_name(tag::driver.c_str()); 00186 else if(tagstr == tag::numeric) 00187 node.set_name(tag::numeric.c_str()); 00188 else if(tagstr == tag::alignment) 00189 node.set_name(tag::alignment.c_str()); 00190 else if(tagstr == tag::value) 00191 node.set_name(tag::value.c_str()); 00192 else if(tagstr == tag::compun) 00193 node.set_name(tag::compun.c_str()); 00194 else if(tagstr == tag::workgrp) 00195 node.set_name(tag::workgrp.c_str()); 00196 else 00197 std::cout << "# Error adding data node: node tag not recognized .." << std::endl; 00198 node.append_child(pugi::node_pcdata).set_value(data.c_str()); 00199 } 00200 00201 void load(std::string filename) 00202 { 00203 doc.load_file(filename.c_str()); 00204 } 00205 00206 void dump(std::string filename) 00207 { 00208 std::ofstream outstream(filename.c_str()); 00209 this->dump(outstream); 00210 outstream.close(); 00211 } 00212 00213 void dump(std::ostream& stream = std::cout) 00214 { 00215 doc.save(stream, " "); 00216 } 00217 00218 pugi::xml_document doc; 00219 pugi::xml_node root; 00220 pugi::xml_node devices; 00221 pugi::xml_node tests; 00222 pugi::xml_node kernels; 00223 pugi::xml_node parameters; 00224 pugi::xml_node last; 00225 00226 bool devices_open; 00227 bool tests_open; 00228 bool kernels_open; 00229 bool parameters_open; 00230 00231 }; 00232 00234 template <typename T> 00235 struct first_letter_of_type 00236 { 00237 static char get(); //intentionally not implemented, class must be specialized 00238 }; 00239 00240 template <> 00241 struct first_letter_of_type <float> 00242 { 00243 static char get() { return 'f'; } 00244 }; 00245 00246 template <> 00247 struct first_letter_of_type <double> 00248 { 00249 static char get() { return 'd'; } 00250 }; 00251 00252 template <typename T> 00253 struct program_for_vcltype 00254 { 00255 static std::string get(); //intentionally not implemented, class must be specialized 00256 }; 00257 00258 template <typename T, unsigned int ALIGNMENT> 00259 struct program_for_vcltype < viennacl::vector<T, ALIGNMENT> > 00260 { 00261 static std::string get() 00262 { 00263 std::stringstream ss; 00264 ss << first_letter_of_type<T>::get() << "_vector_" << ALIGNMENT; 00265 return ss.str(); 00266 } 00267 }; 00268 00269 template <typename T, unsigned int ALIGNMENT> 00270 struct program_for_vcltype < viennacl::matrix<T, row_major, ALIGNMENT> > 00271 { 00272 static std::string get() 00273 { 00274 std::stringstream ss; 00275 ss << first_letter_of_type<T>::get() << "_matrix_row_" << ALIGNMENT; 00276 return ss.str(); 00277 } 00278 }; 00279 00280 template <typename T, unsigned int ALIGNMENT> 00281 struct program_for_vcltype < viennacl::matrix<T, column_major, ALIGNMENT> > 00282 { 00283 static std::string get() 00284 { 00285 std::stringstream ss; 00286 ss << first_letter_of_type<T>::get() << "_matrix_col_" << ALIGNMENT; 00287 return ss.str(); 00288 } 00289 }; 00290 00291 template <typename T, unsigned int ALIGNMENT> 00292 struct program_for_vcltype < viennacl::compressed_matrix<T, ALIGNMENT> > 00293 { 00294 static std::string get() 00295 { 00296 std::stringstream ss; 00297 ss << first_letter_of_type<T>::get() << "_compressed_matrix_" << ALIGNMENT; 00298 return ss.str(); 00299 } 00300 }; 00301 00302 template<typename SCALARTYPE, unsigned int ALIGNMENT> 00303 void set_kernel_params(std::string program_name, 00304 std::string kernel_name, 00305 unsigned int glob, //total no. of threads 00306 unsigned int loc) //threads per work group 00307 { 00308 //get kernel from pool and set work sizes: 00309 viennacl::ocl::kernel & k = viennacl::ocl::get_kernel(program_name, kernel_name); 00310 k.global_work_size(0, glob); 00311 k.local_work_size(0, loc); 00312 00313 //std::cout << "Setting [" << glob << ", " << loc << "] for kernel " << kernel_name << std::endl; 00314 } 00315 00316 template<typename VclBasicType> 00317 void tune_impl(parameter_database& paras, std::string parent) 00318 { 00319 typedef typename VclBasicType::value_type::value_type SCALARTYPE; 00320 00321 // create dummy vectors; the kernels have to be created .. 00322 VclBasicType dummy; 00323 00324 // extract the kernels for which parameters are present 00325 std::string kernel_str = parent+"/kernels/kernel/name/text()"; 00326 pugi::xpath_node_set kernel_res = paras.doc.select_nodes(kernel_str.c_str()); 00327 00328 typedef std::vector<std::string> kernels_type; 00329 kernels_type kernels; 00330 std::cout << "Retrieving kernels..." << std::endl; 00331 for (pugi::xpath_node_set::const_iterator it = kernel_res.begin(); it != kernel_res.end(); ++it) 00332 { 00333 std::stringstream ss; 00334 it->node().print(ss, " "); 00335 std::string kern(ss.str()); 00336 kern.erase(std::remove(kern.begin(), kern.end(), '\n'), kern.end()); //trim trailing linebreak 00337 kernels.push_back(kern); 00338 } 00339 00340 // retrieve the actual parameters 00341 std::cout << "Retrieving actual parameters..." << std::endl; 00342 for(typename kernels_type::iterator iter = kernels.begin(); 00343 iter != kernels.end(); iter++) 00344 { 00345 // retrieving the work group .. 00346 std::string wg_str = parent+"/kernels/kernel[name='"+*iter+"']/params/param[name='"+val::globsize+"']/value/text()"; 00347 pugi::xpath_node_set wg_res = paras.doc.select_nodes(wg_str.c_str()); 00348 00349 unsigned int global_size(0); 00350 00351 std::stringstream ss; 00352 ss << wg_res[0].node().value(); 00353 ss >> global_size; 00354 00355 // retrieving the local_workers .. 00356 std::string lw_str = parent+"/kernels/kernel[name='"+*iter+"']/params/param[name='"+val::locsize+"']/value/text()"; 00357 pugi::xpath_node_set lw_res = paras.doc.select_nodes(lw_str.c_str()); 00358 00359 unsigned int local_workers(0); 00360 00361 ss.clear(); 00362 ss << lw_res[0].node().value(); 00363 ss >> local_workers; 00364 00365 //std::cout << "kernel: " << *iter << " wg: " << work_group << " lw: " << local_workers << std::endl; 00366 00367 // set the parameters 00368 set_kernel_params<SCALARTYPE,1> (program_for_vcltype<VclBasicType>::get(), *iter, global_size, local_workers); 00369 //set_kernel_params<SCALARTYPE,4> (*iter, work_group * local_workers, local_workers); 00370 //set_kernel_params<SCALARTYPE,16>(*iter, work_group * local_workers, local_workers); 00371 } 00372 } 00373 00375 template <typename T> 00376 struct to_string {}; 00377 00378 template <> 00379 struct to_string<float> 00380 { 00381 static std::string get() { return "float"; } 00382 }; 00383 00384 template <> 00385 struct to_string<double> 00386 { 00387 static std::string get() { return "double"; } 00388 }; 00389 00395 template<typename VclBasicType> 00396 void read_kernel_parameters(std::string filename) 00397 { 00398 typedef typename VclBasicType::value_type::value_type SCALARTYPE; 00399 00400 parameter_database paras; 00401 paras.load(filename); 00402 00403 std::string devname = viennacl::ocl::current_device().name(); 00404 00405 // check if tune parameters for the current device are present 00406 std::string device_str = "/parameters/devices/device[name='"+devname+"']"; 00407 pugi::xpath_node_set device_res = paras.doc.select_nodes(device_str.c_str()); 00408 00409 if(device_res.size() == 0) 00410 { 00411 std::cout << "Tuner: There are no parameters for this device present!" << std::endl; 00412 // evaluate the parameters for this device? 00413 } 00414 00415 // check if tune parameters for float exist 00416 std::string numeric_str = device_str+"/tests/test[numeric='"+to_string<SCALARTYPE>::get()+"']"; 00417 pugi::xpath_node_set numeric_res = paras.doc.select_nodes(numeric_str.c_str()); 00418 00419 if(numeric_res.size() > 0) 00420 { 00421 tune_impl<VclBasicType>(paras, numeric_str); 00422 } 00423 else 00424 { 00425 std::cout << "Tuner: There are no parameters for numeric type float present!" << std::endl; 00426 } 00427 00428 // // check if tune parameters for double exist 00429 // std::string double_str = device_str+"/tests/test[numeric='"+val::dbl+"']"; 00430 // pugi::xpath_node_set double_res = paras.doc.select_nodes(double_str.c_str()); 00431 // 00432 // if(double_res.size() > 0) 00433 // { 00434 // tune_impl<double>(paras, double_str); 00435 // } 00436 // else 00437 // { 00438 // std::cout << "Tuner: There are no parameters for numeric type double present!" << std::endl; 00439 // } 00440 00441 } 00442 00443 } // end namespace io 00444 00445 } // end namespace viennacl 00446 00447 #endif
1.7.6.1