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