This file is indexed.

/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