1/*******************************************************************************
2* Copyright 2019-2022 Intel Corporation
3*
4* Licensed under the Apache License, Version 2.0 (the "License");
5* you may not use this file except in compliance with the License.
6* You may obtain a copy of the License at
7*
8* http://www.apache.org/licenses/LICENSE-2.0
9*
10* Unless required by applicable law or agreed to in writing, software
11* distributed under the License is distributed on an "AS IS" BASIS,
12* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13* See the License for the specific language governing permissions and
14* limitations under the License.
15*******************************************************************************/
16
17#ifndef GPU_COMPUTE_KERNEL_CTX_HPP
18#define GPU_COMPUTE_KERNEL_CTX_HPP
19
20#include <cassert>
21#ifdef DEBUG_PRINT
22#include <iostream>
23#endif
24#include <map>
25#include <set>
26#include <sstream>
27#include <string>
28#include <type_traits>
29
30#include "common/bit_cast.hpp"
31#include "common/primitive_attr.hpp"
32#include "gpu/gpu_primitive_attr.hpp"
33
34namespace dnnl {
35namespace impl {
36namespace gpu {
37namespace compute {
38
39class kernel_ctx_t {
40public:
41 kernel_ctx_t(const primitive_attr_t *attr = nullptr) {
42 set_default_options(attr);
43 }
44
45 std::string options() const {
46 std::ostringstream oss;
47 for (auto &opt : option_set_)
48 oss << " " << opt;
49
50 for (auto &int_var : int_var_map_)
51 oss << " -D" << int_var.first << "=" << int_var.second;
52
53 for (auto &float_var : float_var_map_) {
54 oss << " -D" << float_var.first << "=as_float(0x" << std::hex
55 << utils::bit_cast<uint32_t>(float_var.second) << ")";
56 }
57 return oss.str();
58 }
59
60 void define_int(const char *variable, int64_t value) {
61 int_var_map_.insert({variable, value});
62 }
63
64 void define_int(const std::string &variable, int64_t value) {
65 define_int(variable.c_str(), value);
66 }
67
68 // TODO: should be removed, any float values should be passed in
69 // kernel parameters
70 void define_float(const char *variable, float value) {
71 float_var_map_.insert({variable, value});
72 }
73
74 void add_option(const char *option) { option_set_.insert(option); }
75 void add_option(const std::string &option) { add_option(option.c_str()); }
76
77 bool has_macro(const char *name) const {
78 std::string opt_start = std::string("-D") + name + "=";
79 for (auto &opt : option_set_)
80 if (opt.find(opt_start) != std::string::npos) return true;
81
82 return int_var_map_.count(name) != 0 || float_var_map_.count(name) != 0;
83 }
84 bool has_macro(const std::string &name) const {
85 return has_macro(name.c_str());
86 }
87
88 void set_data_type(data_type_t dt) {
89 switch (dt) {
90 case data_type::bf16: define_int("DT_BF16", 1); break;
91 case data_type::f16: define_int("DT_F16", 1); break;
92 case data_type::f32: define_int("DT_F32", 1); break;
93 case data_type::f64: define_int("DT_F64", 1); break;
94 case data_type::s8: define_int("DT_S8", 1); break;
95 case data_type::u8: define_int("DT_U8", 1); break;
96 case data_type::s32: define_int("DT_S32", 1); break;
97 default: assert(!"unknown data type"); break;
98 }
99 }
100
101 void print_options() const {
102#ifdef DEBUG_PRINT
103 std::cout << "OPT:\n" << options() << std::endl;
104#endif
105 }
106
107 template <typename T>
108 T get_scalar(const std::string &s) const {
109 UNUSED(s);
110 static_assert(!std::is_same<T, T>::value, "not expected");
111 return {};
112 }
113
114 std::string data_type() const {
115 if (int_var_map_.count("DT_F16") != 0) return "f16";
116
117 if (int_var_map_.count("DT_F32") != 0) return "f32";
118
119 if (int_var_map_.count("DT_F64") != 0) return "f64";
120
121 if (int_var_map_.count("DT_S8") != 0) return "s8";
122
123 return "";
124 }
125
126private:
127 void set_default_options(const primitive_attr_t *attr) {
128 // By default fp32 division and sqrt are not IEEE-compliant
129 add_option("-cl-fp32-correctly-rounded-divide-sqrt");
130
131 if (attr && attr->gpu_attr_) {
132 auto *gpu_attr = utils::downcast<gpu_primitive_attr_t *>(
133 attr->gpu_attr_.get());
134 if (gpu_attr->threads_per_eu() == 4) {
135 add_option("-cl-intel-256-GRF-per-thread");
136 }
137 }
138 }
139
140 std::map<std::string, int64_t> int_var_map_;
141 std::map<std::string, float> float_var_map_;
142 std::set<std::string> option_set_;
143};
144
145template <>
146inline int64_t kernel_ctx_t::get_scalar(const std::string &name) const {
147 assert(int_var_map_.count(name) != 0 && "not expected");
148 return int_var_map_.at(name);
149}
150
151} // namespace compute
152} // namespace gpu
153} // namespace impl
154} // namespace dnnl
155
156#endif // GPU_COMPUTE_KERNEL_CTX_HPP
157