• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

/data/development/ViennaCL/dev/viennacl/io/kernel_parameters.hpp

Go to the documentation of this file.
00001 #ifndef VIENNACL_IO_KERNEL_PARAMETERS_HPP
00002 #define VIENNACL_IO_KERNEL_PARAMETERS_HPP
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2011, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                   ViennaCL - The Vienna Computing Library
00011                             -----------------
00012 
00013    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00014                
00015    (A list of authors and contributors can be found in the PDF manual)
00016 
00017    License:         MIT (X11), see file LICENSE in the base directory
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     } // end namespace tag
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           // close the current kernels section
00118           // so a new one is created for this new test
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           // close the current parameters section
00143           // so a new one is created for this new kernel
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(); //intentionally not implemented, class must be specialized
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();  //intentionally not implemented, class must be specialized
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, //total no. of threads
00305                           unsigned int loc)  //threads per work group
00306     {
00307       //get kernel from pool and set work sizes:
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       //std::cout << "Setting [" << glob << ", " << loc << "] for kernel " << kernel_name << std::endl;
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       // create dummy vectors; the kernels have to be created ..
00321       VclBasicType    dummy;
00322 
00323       // extract the kernels for which parameters are present
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()); //trim trailing linebreak
00336           kernels.push_back(kern);
00337       }
00338       
00339       // retrieve the actual parameters
00340       std::cout << "Retrieving actual parameters..." << std::endl;
00341       for(typename kernels_type::iterator iter = kernels.begin();
00342           iter != kernels.end(); iter++)
00343       {
00344           // retrieving the work group ..
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           // retrieving the local_workers ..
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           //std::cout << "kernel: " << *iter << " wg: " << work_group << " lw: " << local_workers << std::endl;
00365 
00366           // set the parameters
00367           set_kernel_params<SCALARTYPE,1> (program_for_vcltype<VclBasicType>::get(), *iter, global_size, local_workers);
00368           //set_kernel_params<SCALARTYPE,4> (*iter, work_group * local_workers, local_workers);         
00369           //set_kernel_params<SCALARTYPE,16>(*iter, work_group * local_workers, local_workers);                 
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       // check if tune parameters for the current device are present
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           // evaluate the parameters for this device?
00412       }
00413       
00414       // check if tune parameters for float exist
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   //    // check if tune parameters for double exist
00428   //    std::string          double_str = device_str+"/tests/test[numeric='"+val::dbl+"']";
00429   //    pugi::xpath_node_set double_res = paras.doc.select_nodes(double_str.c_str());
00430   // 
00431   //    if(double_res.size() > 0)
00432   //    {
00433   //       tune_impl<double>(paras, double_str);
00434   //    }
00435   //    else
00436   //    {
00437   //       std::cout << "Tuner: There are no parameters for numeric type double present!" << std::endl;   
00438   //    }
00439 
00440     }
00441 
00442   } // end namespace io
00443 
00444 } // end namespace viennacl
00445 
00446 #endif

Generated on Fri Dec 30 2011 23:20:42 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1