#pragma once
#include <cstring>
#include <executorch/runtime/core/array_ref.h>
#include <executorch/runtime/core/error.h>
#include <executorch/runtime/core/evalue.h>
#include <executorch/runtime/core/exec_aten/exec_aten.h>
#include <executorch/runtime/core/result.h>
#include <executorch/runtime/core/span.h>
#include <executorch/runtime/platform/compiler.h>
#include <executorch/runtime/platform/platform.h>
#if defined(ET_OP_REGISTRY_DEBUG)
#include <ostream>
#endif
#define ET_LOG_KERNEL_KEY(k) \
ET_LOG( \
Info, \
"key: %s, is_fallback: %s", \
k.data(), \
k.is_fallback() ? "true" : "false");
#define ET_LOG_TENSOR_META(meta_list) \
for (const auto& meta : meta_list) { \
ET_LOG(Info, "dtype: %d | dim order: [", int(meta.dtype_)); \
for (size_t i = 0; i < meta.dim_order_.size(); i++) { \
ET_LOG(Info, "%d,", static_cast<int32_t>(meta.dim_order_[i])); \
} \
ET_LOG(Info, "]"); \
}
namespace executorch {
namespace ET_RUNTIME_NAMESPACE {
class KernelRuntimeContext; using OpFunction = void (*)(KernelRuntimeContext&, Span<EValue*>);
struct TensorMeta {
executorch::aten::ScalarType dtype_;
Span<executorch::aten::DimOrderType> dim_order_;
TensorMeta() = default;
TensorMeta(
executorch::aten::ScalarType dtype,
Span<executorch::aten::DimOrderType> order)
: dtype_(dtype), dim_order_(order) {}
bool operator==(const TensorMeta& other) const {
return this->equals(other);
}
bool operator!=(const TensorMeta& other) const {
return !this->equals(other);
}
bool equals(const TensorMeta& other) const {
if (dtype_ != other.dtype_) {
return false;
}
if (dim_order_.size() != other.dim_order_.size()) {
return false;
}
for (size_t i = 0; i < dim_order_.size(); i++) {
if (dim_order_[i] != other.dim_order_[i]) {
return false;
}
}
return true;
}
#if defined(ET_OP_REGISTRY_DEBUG)
friend std::ostream& operator<<(std::ostream& os, const TensorMeta& meta) {
os << "dtype: " << int(meta.dtype_) << " | dim order: [";
for (int i = 0; i < meta.dim_order_.size(); i++) {
os << static_cast<int32_t>(meta.dim_order_[i]) << ", ";
}
os << "]";
return os;
}
#endif
};
struct KernelKey {
public:
constexpr KernelKey() = default;
constexpr KernelKey(const char* kernel_key_data)
: kernel_key_data_(kernel_key_data) {}
bool operator==(const KernelKey& other) const {
return this->equals(other);
}
bool operator!=(const KernelKey& other) const {
return !this->equals(other);
}
bool equals(const KernelKey& other) const {
if (is_fallback() != other.is_fallback()) {
return false;
}
if (is_fallback()) {
return true;
}
return strcmp(kernel_key_data_, other.kernel_key_data_) == 0;
}
bool is_fallback() const {
return kernel_key_data_ == nullptr;
}
const char* data() const {
return kernel_key_data_;
}
#if defined(ET_OP_REGISTRY_DEBUG)
friend std::ostream& operator<<(std::ostream& os, const KernelKey& key) {
os << key.kernel_key_data_ << std::endl;
return os;
}
#endif
private:
const char* kernel_key_data_ = nullptr;
};
struct Kernel {
const char* name_;
KernelKey kernel_key_;
OpFunction op_;
constexpr explicit Kernel(const char* name, OpFunction func)
: name_(name), op_(func) {}
constexpr explicit Kernel(const char* name, KernelKey key, OpFunction func)
: name_(name), kernel_key_(key), op_(func) {}
constexpr Kernel() : name_(nullptr), op_(nullptr) {}
};
namespace internal {
constexpr size_t kKernelKeyBufSize = 659;
Error make_kernel_key_string(
Span<const TensorMeta> key,
char* buf,
size_t buf_size);
}
bool registry_has_op_function(
const char* name,
Span<const TensorMeta> meta_list = {});
::executorch::runtime::Result<OpFunction> get_op_function_from_registry(
const char* name,
Span<const TensorMeta> meta_list = {});
::executorch::runtime::Result<OpFunction> get_op_function_from_registry(
const char* name,
Span<const TensorMeta> meta_list,
Span<const Kernel> kernel_list);
Span<const Kernel> get_registered_kernels();
ET_NODISCARD Error register_kernels(const Span<const Kernel>);
ET_NODISCARD inline Error register_kernel(const Kernel& kernel) {
return register_kernels({&kernel, 1});
};
} }
namespace torch {
namespace executor {
using ::executorch::ET_RUNTIME_NAMESPACE::Kernel;
using ::executorch::ET_RUNTIME_NAMESPACE::KernelKey;
using ::executorch::ET_RUNTIME_NAMESPACE::KernelRuntimeContext;
using ::executorch::ET_RUNTIME_NAMESPACE::OpFunction;
using ::executorch::ET_RUNTIME_NAMESPACE::TensorMeta;
using KernelRuntimeContext =
::executorch::ET_RUNTIME_NAMESPACE::KernelRuntimeContext;
inline ::executorch::runtime::Error register_kernels(ArrayRef<Kernel> kernels) {
return ::executorch::ET_RUNTIME_NAMESPACE::register_kernels(
{kernels.data(), kernels.size()});
}
inline OpFunction getOpsFn(
const char* name,
ArrayRef<TensorMeta> meta_list = {}) {
auto result =
::executorch::ET_RUNTIME_NAMESPACE::get_op_function_from_registry(
name, {meta_list.data(), meta_list.size()});
ET_CHECK(result.ok()); return *result;
}
inline bool hasOpsFn(const char* name, ArrayRef<TensorMeta> meta_list = {}) {
return ::executorch::ET_RUNTIME_NAMESPACE::registry_has_op_function(
name, {meta_list.data(), meta_list.size()});
}
inline ArrayRef<Kernel> get_kernels() {
Span<const Kernel> kernels =
::executorch::ET_RUNTIME_NAMESPACE::get_registered_kernels();
return ArrayRef<Kernel>(kernels.data(), kernels.size());
}
} }