/usr/include/viennacl/generator/autotune.hpp is in libviennacl-dev 1.5.2-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | #ifndef VIENNACL_GENERATOR_AUTOTUNE_HPP
#define VIENNACL_GENERATOR_AUTOTUNE_HPP
/* =========================================================================
Copyright (c) 2010-2014, Institute for Microelectronics,
Institute for Analysis and Scientific Computing,
TU Wien.
Portions of this software are copyright by UChicago Argonne, LLC.
-----------------
ViennaCL - The Vienna Computing Library
-----------------
Project Head: Karl Rupp rupp@iue.tuwien.ac.at
(A list of authors and contributors can be found in the PDF manual)
License: MIT (X11), see file LICENSE in the base directory
============================================================================= */
/** @file viennacl/generator/autotune.hpp
*
* @brief User interface for the autotuning procedure
*/
#include <ctime>
#include <iomanip>
#include <cmath>
#include <iterator>
#include "viennacl/ocl/kernel.hpp"
#include "viennacl/ocl/infos.hpp"
#include "viennacl/scheduler/forwards.h"
#include "viennacl/generator/generate.hpp"
#include "viennacl/tools/timer.hpp"
namespace viennacl{
namespace generator{
namespace autotune{
/** @brief class for a tuning parameter */
class tuning_param{
public:
/** @brief The constructor
*
* @param values The set of values which this particular tuning parameter can take
*/
tuning_param(std::vector<int> const & values) : values_(values){ reset(); }
/** @brief Returns true if the parameter has reached its maximum value */
bool is_max() const { return current_ == (values_.size()-1); }
/** @brief Increments the parameter */
bool inc(){
++current_ ;
if(current_ < values_.size() )
return false;
reset();
return true;
}
/** @brief Returns the current value of the parameter */
int current() const{ return values_[current_]; }
/** @brief Resets the parameter to its minimum value */
void reset() { current_ = 0; }
private:
std::vector<int> values_;
unsigned int current_;
};
/** @brief Tuning configuration
*
* ConfigType must have a profile_type typedef
* ConfigType must implement is_invalid that returns whether or not a given parameter is invalid
* ConfigType must implement create_profile that creates a profile_type given a set of parameters
*
* Parameters are stored in a std::map<std::string, viennacl::generator::autotune::tuning_param>
*/
template<class ConfigType>
class tuning_config{
private:
/** @brief Storage type of the parameters */
typedef std::map<std::string, viennacl::generator::autotune::tuning_param> params_t;
public:
typedef ConfigType config_type;
/** @brief Accessor for profile_type */
typedef typename config_type::profile_type profile_type;
/** @brief Add a tuning parameter to the config */
void add_tuning_param(std::string const & name, std::vector<int> const & values){
params_.insert(std::make_pair(name,values));
}
/** @brief Returns true if the tuning config has still not explored all its possibilities */
bool has_next() const{
bool res = false;
for(typename params_t::const_iterator it = params_.begin() ; it != params_.end() ; ++it)
res = res || !it->second.is_max();
return res;
}
/** @brief Update the parameters of the config */
void update(){
for(typename params_t::iterator it = params_.begin() ; it != params_.end() ; ++it)
if(it->second.inc()==false)
break;
}
/** @brief Returns true if the compilation/execution of the underlying profile has an undefined behavior */
bool is_invalid(viennacl::ocl::device const & dev) const{
return config_type::is_invalid(dev,params_);
}
/** @brief Returns the current profile */
typename config_type::profile_type get_current(){
return config_type::create_profile(params_);
}
/** @brief Reset the config */
void reset(){
for(params_t::iterator it = params_.begin() ; it != params_.end() ; ++it){
it->second.reset();
}
}
private:
params_t params_;
};
/** @brief Add the timing value for a given profile and an statement */
template<class ProfileT>
double benchmark_impl(viennacl::scheduler::statement const & statement, code_generator::forced_profile_key_type key, ProfileT const & prof, unsigned int n_runs){
tools::timer t;
std::list<viennacl::ocl::kernel *> kernels;
viennacl::generator::code_generator gen;
gen.force_profile(key, prof);
gen.add(statement, statement.array()[0]);
viennacl::generator::get_configured_program(gen, kernels, true);
viennacl::generator::enqueue(gen);
viennacl::backend::finish();
t.start();
for(unsigned int i = 0 ; i < n_runs ; ++i)
viennacl::generator::enqueue(gen);
viennacl::backend::finish();
return (double)t.get()/n_runs;
}
/** @brief Fills a timing map for a given statement and a benchmark configuration
*
* @tparam OpT type of the statement
* @tparam ConfigType type of the benchmark configuration
* @param timings the timings to fill
* @param op the given statement
* @param key a key for forcing a particular kernel profile (i.e. to pick profile A for a device which would usually use profile B)
* @param config the given configuration
* @param n_runs Number of runs for the benchmark
* @param out Pointer to output file stream for writing to file (if not NULL)
*/
template<class ConfigType>
void benchmark(std::map<double, typename ConfigType::profile_type> * timings, scheduler::statement const & op, code_generator::forced_profile_key_type const & key, tuning_config<ConfigType> & config, unsigned int n_runs, std::ofstream * out){
viennacl::ocl::device const & dev = viennacl::ocl::current_device();
unsigned int n_conf = 0;
while(config.has_next()){
config.update();
typename ConfigType::profile_type const & profile = config.get_current();
if(config.is_invalid(dev) || profile.is_slow(dev))
continue;
++n_conf;
}
config.reset();
unsigned int n = 0;
while(config.has_next()){
config.update();
typename ConfigType::profile_type const & profile = config.get_current();
if(config.is_invalid(dev) || profile.is_slow(dev))
continue;
double percent = (double)n++*100/n_conf;
double exec_time = benchmark_impl(op,key,profile,n_runs);
timings->insert(std::make_pair(exec_time, profile));
std::cout << '\r' << "Autotuning..." << "[" << std::setprecision(2) << std::setfill (' ') << std::setw(6) << std::fixed << percent << "%" << "]"
<< " | Best : " << timings->begin()->second << " => " << std::scientific << std::right << std::setprecision(2) << timings->begin()->first << std::flush;
if(out)
*out << std::setprecision(3) << std::scientific << exec_time << "," << profile.csv_representation() << std::endl ;
}
std::cout << '\r' << "Autotuning..." << "[100.00%]" << std::endl;
}
}
}
}
#endif // AUTOTUNE_HPP
|