/*******************************************************************************
* Copyright 2019 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
#include <cassert>
#include <string>
#include <vector>
#include <unordered_map>
#ifdef DNNL_DEV_MODE
#include <fstream>
#include <iostream>
#include <sstream>
#endif
#include "common/verbose.hpp"
#include "gpu/intel/utils.hpp"
namespace dnnl {
namespace impl {
namespace gpu {
namespace intel {
@KER_LIST_EXTERN@
@KER_HEADERS_EXTERN@
const char *get_kernel_source(const char *name) {
static const std::unordered_map<std::string, const char *> kernel_list
= { @KER_LIST_ENTRIES@ };
#ifdef DNNL_DEV_MODE
static std::unordered_map<std::string, std::string> custom_kernels;
const std::string runtime_kernel_overrides
= dnnl::impl::gpu::intel::gpu_utils::dev_getenv(
"runtime_kernel_overrides", std::string());
if (!runtime_kernel_overrides.empty()) {
std::istringstream paths_stream(runtime_kernel_overrides);
std::string name_path_pair;
while (std::getline(paths_stream, name_path_pair, ':')) {
std::size_t comma_pos = name_path_pair.find(',');
if (comma_pos == std::string::npos) continue;
std::string kernel_name = name_path_pair.substr(0, comma_pos);
std::string kernel_path = name_path_pair.substr(comma_pos + 1);
if (kernel_name != name) continue;
auto it = custom_kernels.find(kernel_name);
if (it == custom_kernels.end()) {
VDEBUGINFO(1, common, kernel_list,
"loading kernel %s from file %s\n", kernel_name.c_str(),
kernel_path.c_str());
std::ifstream file(kernel_path, std::ios::binary);
gpu_assert(file) << "Could not open runtime_kernel_path file "
<< kernel_path << "\n";
std::stringstream buffer;
buffer << file.rdbuf();
custom_kernels[kernel_name] = buffer.str();
}
return custom_kernels[kernel_name].c_str();
}
}
#endif
if (!name) return nullptr;
std::string kernel_name = name;
// Missing kernels are expected as they may be included via header files to
// enable better reuse between implementations.
gpu_assert(kernel_list.count(kernel_name) <= 1)
<< "Found " << kernel_list.count(kernel_name)
<< " kernels with the name " << name << ". Expected at most 1.";
auto r = kernel_list.find(kernel_name);
return r != kernel_list.end() ? r->second : nullptr;
}
const char *get_kernel_header(const std::string &name) {
static const std::unordered_map<std::string, const char *>
kernel_header_list
= { @KER_HEADER_LIST_ENTRIES@ };
// Used for OpenCL interoperability validation in C++ code
if (name == "dnnl_types.h") return "";
gpu_assert(kernel_header_list.count(name) == 1)
<< "Found " << kernel_header_list.count(name)
<< " headers with the name " << name << ". Expected 1";
return kernel_header_list.at(name);
}
} // namespace intel
} // namespace gpu
} // namespace impl
} // namespace dnnl