Code quality: Large clean-up of the codebase and especially of the include/ folder

This commit is contained in:
Philippe Tillet
2015-08-06 12:05:12 -07:00
parent df9f6142ef
commit db090d7942
68 changed files with 534 additions and 663 deletions

View File

@@ -1,6 +1,5 @@
#include "isaac/array.h"
#include "isaac/symbolic/execute.h"
#include "isaac/tools/timer.hpp"
#ifdef BENCH_CLBLAS
#include "isaac/wrap/clBLAS.h"
#endif
@@ -16,6 +15,9 @@
#include <numeric>
#include <regex>
#include "timer.hpp"
#define HAS_A_BLAS defined(BENCH_CBLAS) or defined(BENCH_CLBLAS) or defined(BENCH_CUBLAS)
namespace isc = isaac;
typedef isc::int_t int_t;

View File

@@ -0,0 +1,41 @@
#ifndef ISAAC_COMMON_EXPRESSION_TYPE_H
#define ISAAC_COMMON_EXPRESSION_TYPE_H
#include <string>
#include <stdexcept>
namespace isaac
{
enum expression_type
{
INVALID_EXPRESSION_TYPE,
AXPY_TYPE,
GER_TYPE,
DOT_TYPE,
GEMV_N_TYPE,
GEMV_T_TYPE,
GEMM_NN_TYPE,
GEMM_TN_TYPE,
GEMM_NT_TYPE,
GEMM_TT_TYPE
};
inline expression_type expression_type_from_string(std::string const & name)
{
if(name=="axpy") return AXPY_TYPE;
if(name=="dot") return DOT_TYPE;
if(name=="ger") return GER_TYPE;
if(name=="gemv_n") return GEMV_N_TYPE;
if(name=="gemv_t") return GEMV_T_TYPE;
if(name=="gemm_nn") return GEMM_NN_TYPE;
if(name=="gemm_nt") return GEMM_NT_TYPE;
if(name=="gemm_tn") return GEMM_TN_TYPE;
if(name=="gemm_tt") return GEMM_TT_TYPE;
throw std::invalid_argument("Unrecognized expression: " + name);
}
}
#endif

View File

@@ -0,0 +1,104 @@
#ifndef ISAAC_COMMON_NUMERIC_TYPE_H
#define ISAAC_COMMON_NUMERIC_TYPE_H
#include "isaac/exception/unknown_datatype.h"
namespace isaac
{
enum numeric_type
{
INVALID_NUMERIC_TYPE = 0,
// BOOL_TYPE,
CHAR_TYPE,
UCHAR_TYPE,
SHORT_TYPE,
USHORT_TYPE,
INT_TYPE,
UINT_TYPE,
LONG_TYPE,
ULONG_TYPE,
// HALF_TYPE,
FLOAT_TYPE,
DOUBLE_TYPE
};
inline std::string to_string(numeric_type const & type)
{
switch (type)
{
// case BOOL_TYPE: return "bool";
case CHAR_TYPE: return "char";
case UCHAR_TYPE: return "uchar";
case SHORT_TYPE: return "short";
case USHORT_TYPE: return "ushort";
case INT_TYPE: return "int";
case UINT_TYPE: return "uint";
case LONG_TYPE: return "long";
case ULONG_TYPE: return "ulong";
// case HALF_TYPE : return "half";
case FLOAT_TYPE : return "float";
case DOUBLE_TYPE : return "double";
default : throw unknown_datatype(type);
}
}
inline numeric_type numeric_type_from_string(std::string const & name)
{
if(name=="float32") return FLOAT_TYPE;
if(name=="float64") return DOUBLE_TYPE;
throw std::invalid_argument("Invalid datatype: " + name);
}
inline unsigned int size_of(numeric_type type)
{
switch (type)
{
// case BOOL_TYPE:
case UCHAR_TYPE:
case CHAR_TYPE: return 1;
// case HALF_TYPE:
case USHORT_TYPE:
case SHORT_TYPE: return 2;
case UINT_TYPE:
case INT_TYPE:
case FLOAT_TYPE: return 4;
case ULONG_TYPE:
case LONG_TYPE:
case DOUBLE_TYPE: return 8;
default: throw unknown_datatype(type);
}
}
template<size_t size, bool is_unsigned>
struct to_int_numeric_type_impl;
#define ISAAC_INSTANTIATE_INT_TYPE_IMPL(SIZE, IS_UNSIGNED, TYPE) \
template<> struct to_int_numeric_type_impl<SIZE, IS_UNSIGNED> { static const numeric_type value = TYPE; }
ISAAC_INSTANTIATE_INT_TYPE_IMPL(1, false, CHAR_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(2, false, SHORT_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(4, false, INT_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(8, false, LONG_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(1, true, UCHAR_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(2, true, USHORT_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(4, true, UINT_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(8, true, ULONG_TYPE);
#undef ISAAC_INSTANTIATE_INT_TYPE_IMPL
template<class T>
struct to_int_numeric_type
{
static const numeric_type value = to_int_numeric_type_impl<sizeof(T), std::is_unsigned<T>::value>::value;
};
template<class T> struct to_numeric_type { static const numeric_type value = to_int_numeric_type<T>::value; };
template<> struct to_numeric_type<float> { static const numeric_type value = FLOAT_TYPE; };
template<> struct to_numeric_type<double> { static const numeric_type value = DOUBLE_TYPE; };
}
#endif

View File

@@ -5,6 +5,9 @@
#include <list>
#include <vector>
#include "isaac/common/expression_type.h"
#include "isaac/common/numeric_type.h"
#include "isaac/driver/common.h"
#include "isaac/defines.h"
#include "isaac/types.h"

View File

@@ -20,9 +20,6 @@ class ISAACAPI Context
friend class CommandQueue;
friend class Buffer;
private:
void init_cache_path();
public:
explicit Context(cl_context const & context, bool take_ownership = true);
explicit Context(Device const & device);

View File

@@ -20,7 +20,7 @@ private:
friend class CommandQueue;
public:
enum class ISAACAPI VENDOR
enum class ISAACAPI Vendor
{
AMD,
INTEL,
@@ -28,7 +28,7 @@ public:
UNKNOWN
};
enum class ISAACAPI ARCHITECTURE
enum class ISAACAPI Architecture
{
HASWELL,
BROADWELL,
@@ -49,8 +49,8 @@ public:
bool operator==(Device const &) const;
bool operator<(Device const &) const;
VENDOR vendor() const;
ARCHITECTURE architecture() const;
Vendor vendor() const;
Architecture architecture() const;
backend_type backend() const;
size_t clock_rate() const;

View File

@@ -10,7 +10,7 @@
#include "isaac/kernels/parse.h"
#include "isaac/kernels/stream.h"
#include "isaac/symbolic/expression.h"
#include "isaac/tools/to_string.hpp"
namespace isaac
{
@@ -115,41 +115,6 @@ protected:
driver::Kernel & kernel_;
};
struct loop_body_base
{
virtual void operator()(kernel_generation_stream & stream, unsigned int simd_width) const = 0;
};
static void fetching_loop_info(fetching_policy_type policy, std::string const & bound, kernel_generation_stream & stream,
std::string & init, std::string & upper_bound, std::string & inc, std::string const & domain_id, std::string const & domain_size, driver::Device const & device);
template<class Fun>
static void element_wise_loop_1D(kernel_generation_stream & stream, fetching_policy_type fetch, unsigned int simd_width,
std::string const & i, std::string const & bound, std::string const & domain_id, std::string const & domain_size, driver::Device const & device, Fun const & generate_body)
{
std::string strwidth = tools::to_string(simd_width);
std::string boundround = bound + "/" + strwidth;
std::string init, upper_bound, inc;
fetching_loop_info(fetch, boundround, stream, init, upper_bound, inc, domain_id, domain_size, device);
stream << "for(unsigned int " << i << " = " << init << "; " << i << " < " << upper_bound << "; " << i << " += " << inc << ")" << std::endl;
stream << "{" << std::endl;
stream.inc_tab();
generate_body(simd_width);
stream.dec_tab();
stream << "}" << std::endl;
if (simd_width>1)
{
stream << "for(unsigned int " << i << " = " << boundround << "*" << strwidth << " + " << domain_id << "; " << i << " < " << bound << "; " << i << " += " + domain_size + ")" << std::endl;
stream << "{" << std::endl;
stream.inc_tab();
generate_body(1);
stream.dec_tab();
stream << "}" << std::endl;
}
}
static void compute_dot(kernel_generation_stream & os, std::string acc, std::string cur, op_element const & op);
static void compute_index_dot(kernel_generation_stream & os, std::string acc, std::string cur, std::string const & acc_value, std::string const & cur_value, op_element const & op);
static void process_all(std::string const & type_key, std::string const & str, kernel_generation_stream & stream, std::vector<mapping_type> const & mappings);

View File

@@ -0,0 +1,33 @@
#ifndef ISAAC_MODEL_DATABASE_H
#define ISAAC_MODEL_DATABASE_H
#include <map>
#include <memory>
#include "isaac/driver/command_queue.h"
#include "isaac/driver/device.h"
#include "isaac/common/expression_type.h"
#include "isaac/common/numeric_type.h"
#include "isaac/model/model.h"
namespace isaac
{
struct database
{
public:
typedef std::map<std::pair<expression_type, numeric_type>, std::shared_ptr<model> > map_type;
private:
static void import(std::string const & fname, driver::CommandQueue const & queue);
static map_type & init(driver::CommandQueue const & queue);
public:
static map_type & get(driver::CommandQueue const & queue);
static void set(driver::CommandQueue const & queue, expression_type operation, numeric_type dtype, std::shared_ptr<model> const & model);
private:
static const std::map<std::tuple<driver::Device::Vendor, driver::Device::Architecture> , const char *> presets_;
static std::map<driver::CommandQueue, map_type> cache_;
};
}
#endif

View File

@@ -38,21 +38,6 @@ namespace isaac
driver::ProgramCache & cache_;
};
class models
{
public:
typedef std::map<std::pair<expression_type, numeric_type>, std::shared_ptr<model> > map_type;
private:
static void import(std::string const & fname, driver::CommandQueue const & queue);
static map_type & init(driver::CommandQueue const & queue);
public:
static map_type & get(driver::CommandQueue const & queue);
static void set(driver::CommandQueue const & queue, expression_type operation, numeric_type dtype, std::shared_ptr<model> const & model);
private:
static std::map<driver::CommandQueue, map_type> data_;
static const std::map<std::pair<driver::Device::VENDOR, driver::Device::ARCHITECTURE> , const char *> database_;
};
extern std::map<std::pair<expression_type, numeric_type>, std::shared_ptr<templates::base> > fallbacks;
}

View File

@@ -1,14 +1,14 @@
#ifndef _ISAAC_SCHEDULER_EXECUTE_H
#define _ISAAC_SCHEDULER_EXECUTE_H
#include "isaac/model/model.h"
#include "isaac/model/database.h"
#include "isaac/symbolic/expression.h"
namespace isaac
{
/** @brief Executes a array_expression on the given queue for the given models map*/
void execute(controller<array_expression> const & , models::map_type &);
void execute(controller<array_expression> const & , database::map_type &);
}

View File

@@ -1,41 +0,0 @@
#ifndef ISAAC_TOOLS_MAKE_MAP_HPP
#define ISAAC_TOOLS_MAKE_MAP_HPP
#include <vector>
namespace isaac
{
namespace tools
{
template<typename MapT>
class make_map
{
typedef typename MapT::key_type T;
typedef typename MapT::mapped_type U;
public:
make_map(const T& key, const U& val)
{
map_.insert(std::make_pair(key,val));
}
make_map<MapT>& operator()(const T& key, const U& val)
{
map_.insert(std::make_pair(key,val));
return *this;
}
operator MapT()
{
return map_;
}
private:
MapT map_;
};
}
}
#endif

View File

@@ -1,32 +0,0 @@
#ifndef ISAAC_TOOLS_MAKE_VECTOR_HPP
#define ISAAC_TOOLS_MAKE_VECTOR_HPP
#include <vector>
namespace isaac
{
namespace tools
{
template <typename T>
class make_vector
{
public:
typedef make_vector<T> my_type;
my_type& operator<< (const T& val) {
data_.push_back(val);
return *this;
}
operator std::vector<T>() const {
return data_;
}
private:
std::vector<T> data_;
};
}
}
#endif

View File

@@ -1,122 +0,0 @@
/* =========================================================================
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
============================================================================= */
#ifndef _ISAAC_TOOLS_TIMER_HPP_
#define _ISAAC_TOOLS_TIMER_HPP_
/** @file isaac/tools/timer.hpp
@brief A simple, yet (mostly) sufficiently accurate timer for benchmarking and profiling. */
#include <iostream>
#ifdef _WIN32
#define WINDOWS_LEAN_AND_MEAN
#include <windows.h>
#undef min
#undef max
namespace isaac
{
namespace tools
{
/** @brief Simple timer class based on gettimeofday (POSIX) or QueryPerformanceCounter (Windows).
*
* Avoids messing with Boost and should be sufficient for benchmarking purposes.
*/
class timer
{
public:
timer()
{
QueryPerformanceFrequency(&freq);
}
void start()
{
QueryPerformanceCounter((LARGE_INTEGER*) &start_time);
}
double get() const
{
LARGE_INTEGER elapsed;
QueryPerformanceCounter((LARGE_INTEGER*) &end_time);
elapsed.QuadPart = end_time.QuadPart - start_time.QuadPart;
return elapsed.QuadPart / static_cast<double>(freq.QuadPart);
}
private:
LARGE_INTEGER freq;
LARGE_INTEGER start_time;
LARGE_INTEGER end_time;
};
}
}
#else
#include <sys/time.h>
namespace isaac
{
namespace tools
{
/** @brief Simple timer class based on gettimeofday (POSIX) or QueryPerformanceCounter (Windows).
*
* Avoids messing with Boost and should be sufficient for benchmarking purposes.
*/
class timer
{
public:
timer() : ts(0)
{}
void start()
{
struct timeval tval;
gettimeofday(&tval, NULL);
ts = static_cast<double>(tval.tv_sec * 1000000 + tval.tv_usec);
}
double get() const
{
struct timeval tval;
gettimeofday(&tval, NULL);
double end_time = static_cast<double>(tval.tv_sec * 1000000 + tval.tv_usec);
return static_cast<double>(end_time-ts) / 1000000.0;
}
private:
double ts;
};
}
}
#endif
#endif

View File

@@ -2,8 +2,8 @@
#define ISAAC_TYPES_H
#include <list>
#include <cstddef>
#include "isaac/defines.h"
#include "isaac/exception/unknown_datatype.h"
namespace isaac
{
@@ -37,106 +37,6 @@ struct repeat_infos
int_t rep2;
};
enum numeric_type
{
INVALID_NUMERIC_TYPE = 0,
// BOOL_TYPE,
CHAR_TYPE,
UCHAR_TYPE,
SHORT_TYPE,
USHORT_TYPE,
INT_TYPE,
UINT_TYPE,
LONG_TYPE,
ULONG_TYPE,
// HALF_TYPE,
FLOAT_TYPE,
DOUBLE_TYPE
};
inline std::string numeric_type_to_string(numeric_type const & type)
{
switch (type)
{
// case BOOL_TYPE: return "bool";
case CHAR_TYPE: return "char";
case UCHAR_TYPE: return "uchar";
case SHORT_TYPE: return "short";
case USHORT_TYPE: return "ushort";
case INT_TYPE: return "int";
case UINT_TYPE: return "uint";
case LONG_TYPE: return "long";
case ULONG_TYPE: return "ulong";
// case HALF_TYPE : return "half";
case FLOAT_TYPE : return "float";
case DOUBLE_TYPE : return "double";
default : throw unknown_datatype(type);
}
}
inline unsigned int size_of(numeric_type type)
{
switch (type)
{
// case BOOL_TYPE:
case UCHAR_TYPE:
case CHAR_TYPE: return 1;
// case HALF_TYPE:
case USHORT_TYPE:
case SHORT_TYPE: return 2;
case UINT_TYPE:
case INT_TYPE:
case FLOAT_TYPE: return 4;
case ULONG_TYPE:
case LONG_TYPE:
case DOUBLE_TYPE: return 8;
default: throw unknown_datatype(type);
}
}
template<size_t size, bool is_unsigned>
struct to_int_numeric_type_impl;
#define ISAAC_INSTANTIATE_INT_TYPE_IMPL(SIZE, IS_UNSIGNED, TYPE) \
template<> struct to_int_numeric_type_impl<SIZE, IS_UNSIGNED> { static const numeric_type value = TYPE; }
ISAAC_INSTANTIATE_INT_TYPE_IMPL(1, false, CHAR_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(2, false, SHORT_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(4, false, INT_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(8, false, LONG_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(1, true, UCHAR_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(2, true, USHORT_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(4, true, UINT_TYPE);
ISAAC_INSTANTIATE_INT_TYPE_IMPL(8, true, ULONG_TYPE);
#undef ISAAC_INSTANTIATE_INT_TYPE_IMPL
template<class T>
struct to_int_numeric_type
{ static const numeric_type value = to_int_numeric_type_impl<sizeof(T), std::is_unsigned<T>::value>::value; };
template<class T> struct to_numeric_type { static const numeric_type value = to_int_numeric_type<T>::value; };
template<> struct to_numeric_type<float> { static const numeric_type value = FLOAT_TYPE; };
template<> struct to_numeric_type<double> { static const numeric_type value = DOUBLE_TYPE; };
enum expression_type
{
INVALID_EXPRESSION_TYPE,
AXPY_TYPE,
GER_TYPE,
DOT_TYPE,
GEMV_N_TYPE,
GEMV_T_TYPE,
GEMM_NN_TYPE,
GEMM_TN_TYPE,
GEMM_NT_TYPE,
GEMM_TT_TYPE
};
struct slice
{
slice(int_t _start, int_t _end, int_t _stride = 1) : start(_start), size((_end - _start)/_stride), stride(_stride) { }

View File

@@ -1,10 +1,11 @@
#Database
set(DATABASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/model/database/")
set(DATABASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/model/presets/")
file(GLOB_RECURSE JSON_FILES "${DATABASE_PATH}/json/*.json")
CODE_TO_H(SOURCES ${JSON_FILES} VARNAME json_files EXTENSION "hpp" OUTPUT_DIR "${DATABASE_PATH}"
NAMESPACE "isaac database" TARGET database EOF "0")
NAMESPACE "isaac presets" TARGET database EOF "0")
#Compilation
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/tools")
if(ANDROID)
add_library(isaac STATIC ${LIBISAAC_SRC})
else()

View File

@@ -4,7 +4,7 @@
#include "isaac/array.h"
#include "isaac/exception/unknown_datatype.h"
#include "isaac/model/model.h"
#include "isaac/model/database.h"
#include "isaac/symbolic/execute.h"
@@ -169,7 +169,7 @@ array& array::operator=(controller<TYPE> const & c)
assert(dtype_ == c.x().dtype());
array_expression expression(*this, c.x(), op_element(OPERATOR_BINARY_TYPE_FAMILY, OPERATOR_ASSIGN_TYPE), context_, dtype_, shape_);
execute(controller<array_expression>(expression, c.execution_options(), c.dispatcher_options(), c.compilation_options()),
isaac::models::get(c.execution_options().queue(context_)));
isaac::database::get(c.execution_options().queue(context_)));
return *this;
}

View File

@@ -1,8 +1,10 @@
#include <iostream>
#include "isaac/driver/context.h"
#include "helpers/ocl/infos.hpp"
#include "isaac/driver/program.h"
#include "isaac/tools/getenv.hpp"
#include "helpers/ocl/infos.hpp"
#include "getenv.hpp"
namespace isaac
{
@@ -10,32 +12,13 @@ namespace isaac
namespace driver
{
void Context::init_cache_path()
{
#ifndef ANDROID
#ifdef _MSC_VER
char* cache_path = 0;
std::size_t sz = 0;
_dupenv_s(&cache_path, &sz, "ISAAC_CACHE_PATH");
#else
const char * cache_path = std::getenv("ISAAC_CACHE_PATH");
#endif
if (cache_path)
cache_path_ = cache_path;
else
#endif
cache_path_ = "";
}
Context::Context(cl_context const & context, bool take_ownership) : backend_(OPENCL), device_(ocl::info<CL_CONTEXT_DEVICES>(context)[0], false), cache_path_(tools::getenv("ISAAC_CACHE_PATH")), h_(backend_, take_ownership)
{
init_cache_path();
h_.cl() = context;
}
Context::Context(Device const & device) : backend_(device.backend_), device_(device), cache_path_(tools::getenv("ISAAC_CACHE_PATH")), h_(backend_, true)
{
init_cache_path();
switch(backend_)
{
#ifdef ISAAC_WITH_CUDA

View File

@@ -40,31 +40,31 @@ bool Device::operator<(Device const & other) const
Device::VENDOR Device::vendor() const
Device::Vendor Device::vendor() const
{
std::string vname = vendor_str();
std::transform(vname.begin(), vname.end(), vname.begin(), ::tolower);
if(vname.find("nvidia")!=std::string::npos)
return VENDOR::NVIDIA;
return Vendor::NVIDIA;
else if(vname.find("intel")!=std::string::npos)
return VENDOR::INTEL;
return Vendor::INTEL;
else if(vname.find("amd")!=std::string::npos || vname.find("advanced micro devices")!=std::string::npos)
return VENDOR::AMD;
return Vendor::AMD;
else
return VENDOR::UNKNOWN;
return Vendor::UNKNOWN;
}
Device::ARCHITECTURE Device::architecture() const
Device::Architecture Device::architecture() const
{
switch(vendor())
{
case VENDOR::INTEL:
case Vendor::INTEL:
{
return ARCHITECTURE::BROADWELL;
return Architecture::BROADWELL;
}
default:
{
return ARCHITECTURE::UNKNOWN;
return Architecture::UNKNOWN;
}
}
}

View File

@@ -1,9 +1,10 @@
#include "isaac/driver/platform.h"
#include "isaac/driver/device.h"
#include "isaac/tools/to_string.hpp"
#include "helpers/ocl/infos.hpp"
#include "to_string.hpp"
namespace isaac
{

View File

@@ -3,13 +3,14 @@
#include "isaac/driver/program.h"
#include "isaac/driver/context.h"
#include "isaac/tools/sha1.hpp"
#ifdef ISAAC_WITH_CUDA
#include "helpers/cuda/vector.hpp"
#endif
#include "helpers/ocl/infos.hpp"
#include "sha1.hpp"
namespace isaac
{

View File

@@ -1,5 +1,6 @@
#include "isaac/exception/unknown_datatype.h"
#include "isaac/tools/to_string.hpp"
#include "to_string.hpp"
namespace isaac
{

View File

@@ -7,8 +7,9 @@
#include "isaac/kernels/parse.h"
#include "isaac/kernels/stream.h"
#include "isaac/symbolic/expression.h"
#include "isaac/tools/to_string.hpp"
#include "isaac/tools/find_and_replace.hpp"
#include "to_string.hpp"
#include "find_and_replace.hpp"
namespace isaac
{

View File

@@ -1,12 +1,14 @@
#include <iostream>
#include <cstring>
#include <algorithm>
#include "isaac/kernels/templates/axpy.h"
#include "isaac/kernels/keywords.h"
#include "isaac/driver/backend.h"
#include "isaac/tools/make_map.hpp"
#include "isaac/tools/make_vector.hpp"
#include "isaac/tools/to_string.hpp"
#include <iostream>
#include "tools/loop.hpp"
#include "to_string.hpp"
namespace isaac
{
@@ -83,7 +85,7 @@ std::string axpy::generate_impl(std::string const & suffix, expressions_tuple co
stream << "if(idx==0)" << std::endl;
stream << "{" << std::endl;
stream.inc_tab();
process(stream, LHS_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("array0", "#pointer[#start] = #namereg;"), expressions, mappings);
process(stream, LHS_NODE_TYPE, { {"array0", "#pointer[#start] = #namereg;"} }, expressions, mappings);
stream.dec_tab();
stream << "}" << std::endl;
@@ -107,7 +109,7 @@ axpy::axpy(unsigned int simd, unsigned int ls, unsigned int ng,
std::vector<int_t> axpy::input_sizes(expressions_tuple const & expressions) const
{
size4 shape = static_cast<array_expression const *>(expressions.data().front().get())->shape();
return tools::make_vector<int_t>() << std::max(shape[0], shape[1]);
return {std::max(shape[0], shape[1])};
}
void axpy::enqueue(driver::CommandQueue & queue, driver::Program const & program, std::string const & suffix, base & fallback, controller<expressions_tuple> const & controller)

View File

@@ -12,10 +12,10 @@
#include "isaac/kernels/parse.h"
#include "isaac/exception/operation_not_supported.h"
#include "isaac/exception/unknown_datatype.h"
#include "isaac/tools/to_string.hpp"
#include "isaac/tools/make_map.hpp"
#include "isaac/symbolic/io.h"
#include "to_string.hpp"
namespace isaac
{
namespace templates
@@ -36,20 +36,20 @@ numeric_type base::map_functor::get_numeric_type(isaac::array_expression const *
template<class T>
std::shared_ptr<mapped_object> base::map_functor::binary_leaf(isaac::array_expression const * array_expression, int_t root_idx, mapping_type const * mapping) const
{
return std::shared_ptr<mapped_object>(new T(numeric_type_to_string(array_expression->dtype()), binder_.get(), mapped_object::node_info(mapping, array_expression, root_idx)));
return std::shared_ptr<mapped_object>(new T(to_string(array_expression->dtype()), binder_.get(), mapped_object::node_info(mapping, array_expression, root_idx)));
}
/** @brief Scalar mapping */
std::shared_ptr<mapped_object> base::map_functor::create(numeric_type dtype, values_holder) const
{
std::string strdtype = numeric_type_to_string(dtype);
std::string strdtype = to_string(dtype);
return std::shared_ptr<mapped_object>(new mapped_host_scalar(strdtype, binder_.get()));
}
/** @brief Vector mapping */
std::shared_ptr<mapped_object> base::map_functor::create(array const * a) const
{
std::string dtype = numeric_type_to_string(a->dtype());
std::string dtype = to_string(a->dtype());
unsigned int id = binder_.get(a->data());
//Scalar
if(a->shape()[0]==1 && a->shape()[1]==1)
@@ -279,11 +279,12 @@ std::string base::generate_arguments(std::string const & data_type, driver::Devi
{
std::string kwglobal = Global(device.backend()).get();
std::string _size_t = size_type(device);
return generate_arguments(mappings, tools::make_map<std::map<std::string, std::string> >("array0", kwglobal + " #scalartype* #pointer, " + _size_t + " #start,")
("host_scalar", "#scalartype #name,")
("array1", kwglobal + " " + data_type + "* #pointer, " + _size_t + " #start, " + _size_t + " #stride,")
("array2", kwglobal + " " + data_type + "* #pointer, " + _size_t + " #ld, " + _size_t + " #start1, " + _size_t + " #start2, " + _size_t + " #stride1, " + _size_t + " #stride2,")
("tuple4", "#scalartype #name0, #scalartype #name1, #scalartype #name2, #scalartype #name3,"), expressions);
return generate_arguments(mappings, { {"array0", kwglobal + " #scalartype* #pointer, " + _size_t + " #start,"},
{"host_scalar", "#scalartype #name,"},
{"array1", kwglobal + " " + data_type + "* #pointer, " + _size_t + " #start, " + _size_t + " #stride,"},
{"array2", kwglobal + " " + data_type + "* #pointer, " + _size_t + " #ld, " + _size_t + " #start1, " + _size_t + " #start2, " + _size_t + " #stride1, " + _size_t + " #stride2,"},
{"tuple4", "#scalartype #name0, #scalartype #name1, #scalartype #name2, #scalartype #name3,"}}
, expressions);
}
@@ -306,30 +307,6 @@ const char* base::invalid_exception::what() const throw() { return message_.c_st
base::invalid_exception::~invalid_exception() throw() {}
void base::fetching_loop_info(fetching_policy_type policy, std::string const & bound, kernel_generation_stream & stream, std::string & init, std::string & upper_bound, std::string & inc, std::string const & domain_id, std::string const & domain_size, driver::Device const & device)
{
if (policy==FETCH_FROM_GLOBAL_STRIDED)
{
init = domain_id;
upper_bound = bound;
inc = domain_size;
}
else if (policy==FETCH_FROM_GLOBAL_CONTIGUOUS)
{
std::string _size_t = size_type(device);
std::string chunk_size = "chunk_size";
std::string chunk_start = "chunk_start";
std::string chunk_end = "chunk_end";
stream << _size_t << " " << chunk_size << " = (" << bound << "+" << domain_size << "-1)/" << domain_size << ";" << std::endl;
stream << _size_t << " " << chunk_start << " =" << domain_id << "*" << chunk_size << ";" << std::endl;
stream << _size_t << " " << chunk_end << " = min(" << chunk_start << "+" << chunk_size << ", " << bound << ");" << std::endl;
init = chunk_start;
upper_bound = chunk_end;
inc = "1";
}
}
bool base::is_node_trans(array_expression::container_type const & array, size_t root_idx, leaf_t leaf_type)
{
bool res = false;

View File

@@ -1,10 +1,12 @@
#include <cstring>
#include <iostream>
#include "isaac/kernels/templates/dot.h"
#include "isaac/tools/to_string.hpp"
#include "isaac/tools/make_map.hpp"
#include "isaac/tools/make_vector.hpp"
#include "isaac/kernels/keywords.h"
#include "tools/loop.hpp"
#include "to_string.hpp"
namespace isaac
{
namespace templates
@@ -73,7 +75,7 @@ std::string dot::generate_impl(std::string const & suffix, expressions_tuple con
std::string arguments = _size_t + " N, ";
for (unsigned int k = 0; k < N; ++k)
{
std::string numeric_type = numeric_type_to_string(lhs_most(exprs[k]->array_expression().tree(), exprs[k]->array_expression().root()).lhs.dtype);
std::string numeric_type = to_string(lhs_most(exprs[k]->array_expression().tree(), exprs[k]->array_expression().root()).lhs.dtype);
if (exprs[k]->is_index_dot())
{
arguments += exprs[k]->process(Global(backend).get() + " unsigned int* #name_temp, ");
@@ -276,7 +278,7 @@ std::vector<int_t> dot::input_sizes(expressions_tuple const & expressions) const
{
std::vector<size_t> dots_idx = filter_nodes(&is_dot, *(expressions.data().front()), false);
int_t N = vector_size(lhs_most(expressions.data().front()->tree(), dots_idx[0]));
return tools::make_vector<int_t>() << N;
return {N};
}
void dot::enqueue(driver::CommandQueue & queue, driver::Program const & program, std::string const & suffix, base & fallback, controller<expressions_tuple> const & controller)

View File

@@ -4,9 +4,9 @@
#include "isaac/model/model.h"
#include "isaac/symbolic/preset.h"
#include "isaac/exception/operation_not_supported.h"
#include "isaac/tools/make_vector.hpp"
#include "isaac/tools/to_string.hpp"
#include "isaac/tools/miscellaneous.hpp"
#include "to_string.hpp"
#include "align.hpp"
namespace isaac
{
@@ -118,7 +118,7 @@ gemm_parameters::gemm_parameters(unsigned int simd_width
kernel_generation_stream stream;
array_expression const & st = (*expressions.data().front());
numeric_type dtype = lhs_most(st.tree(), st.root()).lhs.dtype;
std::string sdtype = numeric_type_to_string(dtype);
std::string sdtype = to_string(dtype);
std::string vdtype = append_width(sdtype, p_.simd_width);
std::string _size_t = size_type(device);
std::string vint = append_width("int", p_.simd_width);

View File

@@ -3,9 +3,10 @@
#include "isaac/kernels/stream.h"
#include "isaac/kernels/keywords.h"
#include "isaac/kernels/templates/gemv.h"
#include "isaac/tools/to_string.hpp"
#include "isaac/tools/make_map.hpp"
#include "isaac/tools/make_vector.hpp"
#include "to_string.hpp"
#include "tools/loop.hpp"
namespace isaac
{
@@ -59,7 +60,7 @@ std::string gemv::generate_impl(std::string const & suffix, expressions_tuple co
std::string arguments = _size_t + " M, " + _size_t + " N, " ;
for (const auto & e : dots)
{
std::string numeric_type = numeric_type_to_string(lhs_most(e->array_expression().tree(), e->array_expression().root()).lhs.dtype);
std::string numeric_type = to_string(lhs_most(e->array_expression().tree(), e->array_expression().root()).lhs.dtype);
if (e->is_index_dot())
{
arguments += e->process(Global(backend).get() + " unsigned int* #name_temp, ");
@@ -333,7 +334,7 @@ std::vector<int_t> gemv::input_sizes(expressions_tuple const & expressions) cons
std::pair<int_t, int_t> MN = matrix_size(lhs_most(first_expression.tree(), idx[0]));
if(dot_type_==REDUCE_COLUMNS)
std::swap(MN.first,MN.second);
return tools::make_vector<int_t>() << MN.first << MN.second;
return {MN.first, MN.second};
}
void gemv::enqueue(driver::CommandQueue & queue, driver::Program const & program, std::string const & suffix, base & fallback, controller<expressions_tuple> const & controller)

View File

@@ -1,11 +1,11 @@
#include <cstring>
#include <iostream>
#include "isaac/kernels/templates/ger.h"
#include "isaac/tools/make_map.hpp"
#include "isaac/tools/make_vector.hpp"
#include "isaac/symbolic/io.h"
#include "isaac/kernels/keywords.h"
#include "tools/loop.hpp"
namespace isaac
{
namespace templates
@@ -47,9 +47,10 @@ std::string ger::generate_impl(std::string const & suffix, expressions_tuple con
stream << "{" << std::endl;
stream.inc_tab();
process(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("array0", "#scalartype #namereg = #pointer[#start];")
("array1", "#pointer += #start;")
("array2", "#pointer = &$VALUE{#start1, #start2};"), expressions, mappings);
process(stream, PARENT_NODE_TYPE, { {"array0", "#scalartype #namereg = #pointer[#start];"},
{"array1", "#pointer += #start;"},
{"array2", "#pointer = &$VALUE{#start1, #start2};"}}
, expressions, mappings);
fetching_loop_info(p_.fetching_policy, "M", stream, init0, upper_bound0, inc0, GlobalIdx0(backend).get(), GlobalSize0(backend).get(), device);
stream << "for(" << _size_t << " i = " << init0 << "; i < " << upper_bound0 << "; i += " << inc0 << ")" << std::endl;
@@ -60,25 +61,22 @@ std::string ger::generate_impl(std::string const & suffix, expressions_tuple con
stream << "{" << std::endl;
stream.inc_tab();
process(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >
("array2", data_type + " #namereg = $VALUE{i*#stride1,j*#stride2};")
("vdiag", "#scalartype #namereg = ((i + ((#diag_offset<0)?#diag_offset:0))!=(j-((#diag_offset>0)?#diag_offset:0)))?0:$VALUE{min(i*#stride1, j*#stride1)};")
("repeat", "#scalartype #namereg = $VALUE{(i%#tuplearg0)*#stride1, (j%#tuplearg1)*#stride2};")
("outer", "#scalartype #namereg = ($LVALUE{i*#stride})*($RVALUE{j*#stride});")
process(stream, PARENT_NODE_TYPE, { {"array2", data_type + " #namereg = $VALUE{i*#stride1,j*#stride2};"},
{"vdiag", "#scalartype #namereg = ((i + ((#diag_offset<0)?#diag_offset:0))!=(j-((#diag_offset>0)?#diag_offset:0)))?0:$VALUE{min(i*#stride1, j*#stride1)};"},
{"repeat", "#scalartype #namereg = $VALUE{(i%#tuplearg0)*#stride1, (j%#tuplearg1)*#stride2};"},
{"outer", "#scalartype #namereg = ($LVALUE{i*#stride})*($RVALUE{j*#stride});"} }
, expressions, mappings);
evaluate(stream, PARENT_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >
("array2", "#namereg")
("vdiag", "#namereg")
("repeat", "#namereg")
("array0", "#namereg")
("outer", "#namereg")
("cast", CastPrefix(backend, data_type).get())
("host_scalar", p_.simd_width==1?"#name": InitPrefix(backend, data_type).get() + "(#name)")
evaluate(stream, PARENT_NODE_TYPE, { {"array2", "#namereg"},
{"vdiag", "#namereg"},
{"repeat", "#namereg"},
{"array0", "#namereg"},
{"outer", "#namereg"},
{"cast", CastPrefix(backend, data_type).get()},
{"host_scalar", p_.simd_width==1?"#name": InitPrefix(backend, data_type).get() + "(#name)"}}
, expressions, mappings);
process(stream, LHS_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("array2", "$VALUE{i*#stride1,j*#stride2} = #namereg;")
, expressions, mappings);
process(stream, LHS_NODE_TYPE, { {"array2", "$VALUE{i*#stride1,j*#stride2} = #namereg;"} } , expressions, mappings);
stream.dec_tab();
stream << "}" << std::endl;
@@ -88,7 +86,7 @@ std::string ger::generate_impl(std::string const & suffix, expressions_tuple con
stream << "if(" << GlobalIdx0(backend) << "==0 &&" << GlobalIdx1(backend) << "==0)" << std::endl;
stream << "{" << std::endl;
stream.inc_tab();
process(stream, LHS_NODE_TYPE, tools::make_map<std::map<std::string, std::string> >("array0", "#pointer[#start] = #namereg;"), expressions, mappings);
process(stream, LHS_NODE_TYPE, { {"array0", "#pointer[#start] = #namereg;"} }, expressions, mappings);
stream.dec_tab();
stream << "}" << std::endl;
@@ -111,7 +109,7 @@ std::vector<int_t> ger::input_sizes(expressions_tuple const & expressions) const
{
isaac::array_expression const & array_expression = *(expressions.data().front());
std::pair<int_t, int_t> size = matrix_size(lhs_most(array_expression.tree(), array_expression.root()));
return tools::make_vector<int_t>() << size.first << size.second;
return {size.first, size.second};
}
void ger::enqueue(driver::CommandQueue & /*queue*/, driver::Program const & program, std::string const & suffix, base &, controller<expressions_tuple> const & controller)

View File

@@ -0,0 +1,64 @@
#include "isaac/kernels/stream.h"
#include "isaac/kernels/templates/base.h"
#include <string>
#include "to_string.hpp"
namespace isaac
{
namespace templates
{
inline void fetching_loop_info(fetching_policy_type policy, std::string const & bound, kernel_generation_stream & stream, std::string & init, std::string & upper_bound, std::string & inc, std::string const & domain_id, std::string const & domain_size, driver::Device const & device)
{
if (policy==FETCH_FROM_GLOBAL_STRIDED)
{
init = domain_id;
upper_bound = bound;
inc = domain_size;
}
else if (policy==FETCH_FROM_GLOBAL_CONTIGUOUS)
{
std::string _size_t = size_type(device);
std::string chunk_size = "chunk_size";
std::string chunk_start = "chunk_start";
std::string chunk_end = "chunk_end";
stream << _size_t << " " << chunk_size << " = (" << bound << "+" << domain_size << "-1)/" << domain_size << ";" << std::endl;
stream << _size_t << " " << chunk_start << " =" << domain_id << "*" << chunk_size << ";" << std::endl;
stream << _size_t << " " << chunk_end << " = min(" << chunk_start << "+" << chunk_size << ", " << bound << ");" << std::endl;
init = chunk_start;
upper_bound = chunk_end;
inc = "1";
}
}
template<class Fun>
inline void element_wise_loop_1D(kernel_generation_stream & stream, fetching_policy_type fetch, unsigned int simd_width,
std::string const & i, std::string const & bound, std::string const & domain_id, std::string const & domain_size, driver::Device const & device, Fun const & generate_body)
{
std::string strwidth = tools::to_string(simd_width);
std::string boundround = bound + "/" + strwidth;
std::string init, upper_bound, inc;
fetching_loop_info(fetch, boundround, stream, init, upper_bound, inc, domain_id, domain_size, device);
stream << "for(unsigned int " << i << " = " << init << "; " << i << " < " << upper_bound << "; " << i << " += " << inc << ")" << std::endl;
stream << "{" << std::endl;
stream.inc_tab();
generate_body(simd_width);
stream.dec_tab();
stream << "}" << std::endl;
if (simd_width>1)
{
stream << "for(unsigned int " << i << " = " << boundround << "*" << strwidth << " + " << domain_id << "; " << i << " < " << bound << "; " << i << " += " + domain_size + ")" << std::endl;
stream << "{" << std::endl;
stream.inc_tab();
generate_body(1);
stream.dec_tab();
stream << "}" << std::endl;
}
}
}
}

View File

@@ -1,33 +0,0 @@
#ifndef ISAAC_MODEL_TOOLS_HPP
#define ISAAC_MODEL_TOOLS_HPP
#include <vector>
#include "rapidjson/document.h"
namespace isaac
{
namespace tools
{
template<class T>
std::vector<T> to_int_array(rapidjson::Value const & a)
{
size_t N = a.Size();
std::vector<T> res(N);
for(size_t i = 0 ; i < N ; ++i) res[i] = a[i].GetInt();
return res;
}
template<class T>
std::vector<T> to_float_array(rapidjson::Value const & a)
{
size_t N = a.Size();
std::vector<T> res(N);
for(size_t i = 0 ; i < N ; ++i) res[i] = a[i].GetDouble();
return res;
}
}
}
#endif

144
lib/model/database.cpp Normal file
View File

@@ -0,0 +1,144 @@
#include <fstream>
#include "isaac/model/database.h"
#include "isaac/kernels/parse.h"
#include "isaac/kernels/templates/axpy.h"
#include "isaac/kernels/templates/dot.h"
#include "isaac/kernels/templates/ger.h"
#include "isaac/kernels/templates/gemv.h"
#include "isaac/kernels/templates/gemm.h"
#include "json/rapidjson/document.h"
#include "json/to_array.hpp"
#include "presets/broadwell.hpp"
#include "getenv.hpp"
namespace isaac
{
namespace detail
{
static std::shared_ptr<templates::base> create(std::string const & template_name, std::vector<int> const & a)
{
templates::fetching_policy_type fetch[] = {templates::FETCH_FROM_LOCAL, templates::FETCH_FROM_GLOBAL_STRIDED, templates::FETCH_FROM_GLOBAL_CONTIGUOUS};
if(template_name=="axpy")
return std::shared_ptr<templates::base>(new templates::axpy(a[0], a[1], a[2], fetch[a[3]]));
else if(template_name=="dot")
return std::shared_ptr<templates::base>(new templates::dot(a[0], a[1], a[2], fetch[a[3]]));
else if(template_name=="ger")
return std::shared_ptr<templates::base>(new templates::ger(a[0], a[1], a[2], a[3], a[4], fetch[a[5]]));
else if(template_name.find("gemv_n")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemv_n(a[0], a[1], a[2], a[3], a[4], fetch[a[5]]));
else if(template_name.find("gemv_t")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemv_t(a[0], a[1], a[2], a[3], a[4], fetch[a[5]]));
else if(template_name.find("gemm_nn")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemm_nn(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], fetch[a[8]], fetch[a[9]], a[10], a[11]));
else if(template_name.find("gemm_tn")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemm_tn(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], fetch[a[8]], fetch[a[9]], a[10], a[11]));
else if(template_name.find("gemm_nt")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemm_nt(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], fetch[a[8]], fetch[a[9]], a[10], a[11]));
else if(template_name.find("gemm_tt")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemm_tt(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], fetch[a[8]], fetch[a[9]], a[10], a[11]));
else
throw std::invalid_argument("Invalid expression: " + template_name);
}
}
void database::import(std::string const & fname, driver::CommandQueue const & queue)
{
namespace js = rapidjson;
map_type & result = cache_[queue];
//Parse the JSON document
js::Document document;
std::ifstream t(fname.c_str());
if(!t) return;
std::string str;
t.seekg(0, std::ios::end);
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);
str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
document.Parse<0>(str.c_str());
//Deserialize
std::vector<std::string> operations = {"axpy", "dot", "ger", "gemv_n", "gemv_t", "gemm_nn", "gemm_tn", "gemm_nt", "gemm_tt"};
std::vector<std::string> dtype = {"float32", "float64"};
for(auto & operation : operations)
{
const char * opcstr = operation.c_str();
if(document.HasMember(opcstr))
{
expression_type etype = expression_type_from_string(operation);
for(auto & elem : dtype)
{
const char * dtcstr = elem.c_str();
if(document[opcstr].HasMember(dtcstr))
{
numeric_type dtype = numeric_type_from_string(elem);
// Get profiles
std::vector<std::shared_ptr<templates::base> > templates;
js::Value const & profiles = document[opcstr][dtcstr]["profiles"];
for (js::SizeType id = 0 ; id < profiles.Size() ; ++id)
templates.push_back(detail::create(operation, json::to_int_array<int>(profiles[id])));
if(templates.size()>1)
{
// Get predictor
predictors::random_forest predictor(document[opcstr][dtcstr]["predictor"]);
result[std::make_pair(etype, dtype)] = std::shared_ptr<model>(new model(etype, dtype, predictor, templates, queue));
}
else
result[std::make_pair(etype, dtype)] = std::shared_ptr<model>(new model(etype, dtype, *templates[0], queue));
}
}
}
}
}
database::map_type& database::init(driver::CommandQueue const & queue)
{
map_type & result = cache_[queue];
numeric_type dtypes[] = {CHAR_TYPE, UCHAR_TYPE, SHORT_TYPE, USHORT_TYPE, INT_TYPE, UINT_TYPE, LONG_TYPE, ULONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE};
expression_type etypes[] = {AXPY_TYPE, DOT_TYPE, GER_TYPE, GEMV_N_TYPE, GEMV_T_TYPE, GEMM_NN_TYPE, GEMM_NT_TYPE, GEMM_TN_TYPE, GEMM_TT_TYPE};
for(numeric_type dtype: dtypes)
for(expression_type etype: etypes)
result[std::make_pair(etype, dtype)] = std::shared_ptr<model>(new model(etype, dtype, *fallbacks[std::make_pair(etype, dtype)], queue));
std::string homepath = tools::getenv("HOME");
if(homepath.size())
import(homepath + "/.isaac/devices/device0.json", queue);
return result;
}
database::map_type& database::get(driver::CommandQueue const & queue)
{
std::map<driver::CommandQueue, map_type>::iterator it = cache_.find(queue);
if(it == cache_.end())
return init(queue);
return it->second;
}
void database::set(driver::CommandQueue const & queue, expression_type operation, numeric_type dtype, std::shared_ptr<model> const & model)
{
cache_[queue][std::make_pair(operation,dtype)] = model;
}
std::map<driver::CommandQueue, database::map_type> database::cache_;
//Presets
#define DATABASE_ENTRY(VENDOR, ARCHITECTURE, STRING) \
{std::make_tuple(driver::Device::Vendor::VENDOR, driver::Device::Architecture::ARCHITECTURE), STRING}
const std::map<std::tuple<driver::Device::Vendor, driver::Device::Architecture> , const char *> database::presets_ =
{ DATABASE_ENTRY(INTEL, BROADWELL, presets::broadwell) };
#undef DATABASE_ENTRY
}

View File

@@ -0,0 +1,33 @@
#ifndef ISAAC_MODEL_TOOLS_HPP
#define ISAAC_MODEL_TOOLS_HPP
#include <vector>
#include "rapidjson/document.h"
namespace isaac
{
namespace json
{
template<class T>
std::vector<T> to_int_array(rapidjson::Value const & a)
{
size_t N = a.Size();
std::vector<T> res(N);
for(size_t i = 0 ; i < N ; ++i) res[i] = a[i].GetInt();
return res;
}
template<class T>
std::vector<T> to_float_array(rapidjson::Value const & a)
{
size_t N = a.Size();
std::vector<T> res(N);
for(size_t i = 0 ; i < N ; ++i) res[i] = a[i].GetDouble();
return res;
}
}
}
#endif

View File

@@ -5,7 +5,6 @@
#include <numeric>
#include <memory>
#include "rapidjson/document.h"
#include "isaac/kernels/parse.h"
#include "isaac/kernels/templates/axpy.h"
#include "isaac/kernels/templates/dot.h"
@@ -16,13 +15,8 @@
#include "isaac/exception/unknown_datatype.h"
#include "isaac/exception/operation_not_supported.h"
#include "isaac/model/model.h"
#include "isaac/tools/make_vector.hpp"
#include "isaac/tools/timer.hpp"
#include "isaac/tools/getenv.hpp"
#include "database/broadwell.hpp"
#include "convert.hpp"
#include "getenv.hpp"
namespace isaac
@@ -136,139 +130,6 @@ model::templates_container const & model::templates() const
///////////////////
namespace detail
{
static expression_type get_expression_type(std::string const & name)
{
if(name=="axpy") return AXPY_TYPE;
if(name=="dot") return DOT_TYPE;
if(name=="ger") return GER_TYPE;
if(name=="gemv_n") return GEMV_N_TYPE;
if(name=="gemv_t") return GEMV_T_TYPE;
if(name=="gemm_nn") return GEMM_NN_TYPE;
if(name=="gemm_nt") return GEMM_NT_TYPE;
if(name=="gemm_tn") return GEMM_TN_TYPE;
if(name=="gemm_tt") return GEMM_TT_TYPE;
throw std::invalid_argument("Invalid expression: " + name);
}
static numeric_type get_dtype(std::string const & name)
{
if(name=="float32") return FLOAT_TYPE;
if(name=="float64") return DOUBLE_TYPE;
throw std::invalid_argument("Invalid datatype: " + name);
}
static std::shared_ptr<templates::base> create(std::string const & template_name, std::vector<int> const & a)
{
templates::fetching_policy_type fetch[] = {templates::FETCH_FROM_LOCAL, templates::FETCH_FROM_GLOBAL_STRIDED, templates::FETCH_FROM_GLOBAL_CONTIGUOUS};
if(template_name=="axpy")
return std::shared_ptr<templates::base>(new templates::axpy(a[0], a[1], a[2], fetch[a[3]]));
else if(template_name=="dot")
return std::shared_ptr<templates::base>(new templates::dot(a[0], a[1], a[2], fetch[a[3]]));
else if(template_name=="ger")
return std::shared_ptr<templates::base>(new templates::ger(a[0], a[1], a[2], a[3], a[4], fetch[a[5]]));
else if(template_name.find("gemv_n")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemv_n(a[0], a[1], a[2], a[3], a[4], fetch[a[5]]));
else if(template_name.find("gemv_t")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemv_t(a[0], a[1], a[2], a[3], a[4], fetch[a[5]]));
else if(template_name.find("gemm_nn")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemm_nn(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], fetch[a[8]], fetch[a[9]], a[10], a[11]));
else if(template_name.find("gemm_tn")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemm_tn(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], fetch[a[8]], fetch[a[9]], a[10], a[11]));
else if(template_name.find("gemm_nt")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemm_nt(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], fetch[a[8]], fetch[a[9]], a[10], a[11]));
else if(template_name.find("gemm_tt")!=std::string::npos)
return std::shared_ptr<templates::base>(new templates::gemm_tt(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], fetch[a[8]], fetch[a[9]], a[10], a[11]));
else
throw std::invalid_argument("Invalid expression: " + template_name);
}
}
void models::import(std::string const & fname, driver::CommandQueue const & queue)
{
namespace js = rapidjson;
map_type & result = data_[queue];
//Parse the JSON document
js::Document document;
std::ifstream t(fname.c_str());
if(!t) return;
std::string str;
t.seekg(0, std::ios::end);
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);
str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
document.Parse<0>(str.c_str());
//Deserialize
std::vector<std::string> operations = {"axpy", "dot", "ger", "gemv_n", "gemv_t", "gemm_nn", "gemm_tn", "gemm_nt", "gemm_tt"};
std::vector<std::string> dtype = {"float32", "float64"};
for(auto & operation : operations)
{
const char * opcstr = operation.c_str();
if(document.HasMember(opcstr))
{
expression_type etype = detail::get_expression_type(operation);
for(auto & elem : dtype)
{
const char * dtcstr = elem.c_str();
if(document[opcstr].HasMember(dtcstr))
{
numeric_type dtype = detail::get_dtype(elem);
// Get profiles
std::vector<std::shared_ptr<templates::base> > templates;
js::Value const & profiles = document[opcstr][dtcstr]["profiles"];
for (js::SizeType id = 0 ; id < profiles.Size() ; ++id)
templates.push_back(detail::create(operation, tools::to_int_array<int>(profiles[id])));
if(templates.size()>1)
{
// Get predictor
predictors::random_forest predictor(document[opcstr][dtcstr]["predictor"]);
result[std::make_pair(etype, dtype)] = std::shared_ptr<model>(new model(etype, dtype, predictor, templates, queue));
}
else
result[std::make_pair(etype, dtype)] = std::shared_ptr<model>(new model(etype, dtype, *templates[0], queue));
}
}
}
}
}
models::map_type& models::init(driver::CommandQueue const & queue)
{
map_type & result = data_[queue];
numeric_type dtypes[] = {CHAR_TYPE, UCHAR_TYPE, SHORT_TYPE, USHORT_TYPE, INT_TYPE, UINT_TYPE, LONG_TYPE, ULONG_TYPE, FLOAT_TYPE, DOUBLE_TYPE};
expression_type etypes[] = {AXPY_TYPE, DOT_TYPE, GER_TYPE, GEMV_N_TYPE, GEMV_T_TYPE, GEMM_NN_TYPE, GEMM_NT_TYPE, GEMM_TN_TYPE, GEMM_TT_TYPE};
for(numeric_type dtype: dtypes)
for(expression_type etype: etypes)
result[std::make_pair(etype, dtype)] = std::shared_ptr<model>(new model(etype, dtype, *fallbacks[std::make_pair(etype, dtype)], queue));
std::string homepath = tools::getenv("HOME");
if(homepath.size())
import(homepath + "/.isaac/devices/device0.json", queue);
return result;
}
models::map_type& models::get(driver::CommandQueue const & queue)
{
std::map<driver::CommandQueue, map_type>::iterator it = data_.find(queue);
if(it == data_.end())
return init(queue);
return it->second;
}
void models::set(driver::CommandQueue const & queue, expression_type operation, numeric_type dtype, std::shared_ptr<model> const & model)
{
data_[queue][std::make_pair(operation,dtype)] = model;
}
std::map<driver::CommandQueue, models::map_type> models::data_;
//
std::map<std::pair<expression_type, numeric_type>, std::shared_ptr<templates::base> > init_fallback()
@@ -294,7 +155,4 @@ std::map<std::pair<expression_type, numeric_type>, std::shared_ptr<templates::ba
std::map<std::pair<expression_type, numeric_type>, std::shared_ptr<templates::base> > fallbacks = init_fallback();
const std::map<std::pair<driver::Device::VENDOR, driver::Device::ARCHITECTURE> , const char *>
models::database_ = { { {driver::Device::VENDOR::INTEL, driver::Device::ARCHITECTURE::BROADWELL}, database::broadwell } };
}

View File

@@ -1,5 +1,6 @@
#include "isaac/model/predictors/random_forest.h"
#include "../convert.hpp"
#include "../json/to_array.hpp"
namespace isaac
{
@@ -9,12 +10,12 @@ namespace predictors
random_forest::tree::tree(rapidjson::Value const & treerep)
{
children_left_ = tools::to_int_array<int>(treerep["children_left"]);
children_right_ = tools::to_int_array<int>(treerep["children_right"]);
threshold_ = tools::to_float_array<float>(treerep["threshold"]);
feature_ = tools::to_float_array<float>(treerep["feature"]);
children_left_ = json::to_int_array<int>(treerep["children_left"]);
children_right_ = json::to_int_array<int>(treerep["children_right"]);
threshold_ = json::to_float_array<float>(treerep["threshold"]);
feature_ = json::to_float_array<float>(treerep["feature"]);
for(rapidjson::SizeType i = 0 ; i < treerep["value"].Size() ; i++)
value_.push_back(tools::to_float_array<float>(treerep["value"][i]));
value_.push_back(json::to_float_array<float>(treerep["value"][i]));
D_ = value_[0].size();
}

View File

@@ -4,7 +4,7 @@
namespace isaac
{
namespace database
namespace presets
{
static const char broadwell[] = {

View File

@@ -4,7 +4,7 @@
#include <stdexcept>
#include "isaac/types.h"
#include "isaac/array.h"
#include "isaac/model/model.h"
#include "isaac/model/database.h"
#include "isaac/symbolic/expression.h"
#include "isaac/symbolic/preset.h"
@@ -145,7 +145,7 @@ namespace isaac
}
/** @brief Executes a array_expression on the given models map*/
void execute(controller<array_expression> const & c, models::map_type &models)
void execute(controller<array_expression> const & c, database::map_type & models)
{
array_expression expression = c.x();
driver::Context const & context = expression.context();

View File

@@ -2,7 +2,8 @@
#include <sstream>
#include "isaac/symbolic/io.h"
#include "isaac/tools/to_string.hpp"
#include "to_string.hpp"
namespace isaac
{

View File

@@ -29,7 +29,7 @@ extern "C"
{
std::list<is::driver::Event> levents;
is::execution_options_type options(is::driver::CommandQueue(commandQueues[i],false), &levents, &waitlist);
is::execute(is::control(operation, options), is::models::get(options.queue(context)));
is::execute(is::control(operation, options), is::database::get(options.queue(context)));
if(events)
{
events[i] = levents.front().handle().cl();

View File

@@ -115,7 +115,7 @@ def main():
include =' src/include'.split() + ['external/boost/include', os.path.join(find_module("numpy")[1], "core", "include")]
#Source files
src = 'src/lib/wrap/clBLAS.cpp src/lib/value_scalar.cpp src/lib/kernels/parse.cpp src/lib/kernels/templates/gemm.cpp src/lib/kernels/templates/gemv.cpp src/lib/kernels/templates/ger.cpp src/lib/kernels/templates/dot.cpp src/lib/kernels/templates/axpy.cpp src/lib/kernels/templates/base.cpp src/lib/kernels/stream.cpp src/lib/kernels/mapped_object.cpp src/lib/kernels/keywords.cpp src/lib/kernels/binder.cpp src/lib/array.cpp src/lib/symbolic/preset.cpp src/lib/symbolic/expression.cpp src/lib/symbolic/execute.cpp src/lib/symbolic/io.cpp src/lib/model/model.cpp src/lib/model/predictors/random_forest.cpp src/lib/exception/unknown_datatype.cpp src/lib/exception/operation_not_supported.cpp src/lib/driver/device.cpp src/lib/driver/program.cpp src/lib/driver/event.cpp src/lib/driver/context.cpp src/lib/driver/program_cache.cpp src/lib/driver/platform.cpp src/lib/driver/ndrange.cpp src/lib/driver/kernel.cpp src/lib/driver/handle.cpp src/lib/driver/command_queue.cpp src/lib/driver/check.cpp src/lib/driver/buffer.cpp src/lib/driver/backend.cpp '.split() + [os.path.join('src', 'wrap', sf) for sf in ['_isaac.cpp', 'core.cpp', 'driver.cpp', 'model.cpp', 'exceptions.cpp']]
src = 'src/lib/array.cpp src/lib/wrap/clBLAS.cpp src/lib/value_scalar.cpp src/lib/kernels/mapped_object.cpp src/lib/kernels/parse.cpp src/lib/kernels/templates/base.cpp src/lib/kernels/templates/gemm.cpp src/lib/kernels/templates/gemv.cpp src/lib/kernels/templates/ger.cpp src/lib/kernels/templates/dot.cpp src/lib/kernels/templates/axpy.cpp src/lib/kernels/stream.cpp src/lib/kernels/keywords.cpp src/lib/kernels/binder.cpp src/lib/symbolic/preset.cpp src/lib/symbolic/expression.cpp src/lib/symbolic/execute.cpp src/lib/symbolic/io.cpp src/lib/model/model.cpp src/lib/model/database.cpp src/lib/model/predictors/random_forest.cpp src/lib/exception/unknown_datatype.cpp src/lib/exception/operation_not_supported.cpp src/lib/driver/program.cpp src/lib/driver/device.cpp src/lib/driver/event.cpp src/lib/driver/program_cache.cpp src/lib/driver/ndrange.cpp src/lib/driver/kernel.cpp src/lib/driver/handle.cpp src/lib/driver/command_queue.cpp src/lib/driver/check.cpp src/lib/driver/buffer.cpp src/lib/driver/backend.cpp src/lib/driver/context.cpp src/lib/driver/platform.cpp '.split() + [os.path.join('src', 'wrap', sf) for sf in ['_isaac.cpp', 'core.cpp', 'driver.cpp', 'model.cpp', 'exceptions.cpp']]
boostsrc = 'external/boost/libs/'
for s in ['numpy','python','smart_ptr','system','thread']:
src = src + [x for x in recursive_glob('external/boost/libs/' + s + '/src/','.cpp') if 'win32' not in x and 'pthread' not in x]

View File

@@ -143,7 +143,7 @@ void export_driver()
.add_property("name",&isc::driver::Platform::name)
;
bp::enum_<isaac::driver::Device::VENDOR>
bp::enum_<isaac::driver::Device::Vendor>
("vendor")
.value("AMD", isc::driver::Device::AMD)
.value("INTEL", isc::driver::Device::INTEL)