Skip to content

[4/N] Add backend options map #11462

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: gh/cccclai/24/base
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 89 additions & 91 deletions runtime/backend/backend_options.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,94 +6,92 @@
* LICENSE file in the root directory of this source tree.
*/

#pragma once
#include <executorch/runtime/core/error.h>
#include <cstddef>
#include <cstring>
#include <executorch/runtime/core/array_ref.h>
#include <executorch/runtime/core/error.h>
#include <variant>

namespace executorch {
namespace runtime {

// Strongly-typed option key template
template <typename T>
struct OptionKey {
const char* key;
constexpr explicit OptionKey(const char* k) : key(k) {}
};

// Union replaced with std::variant
using OptionValue = std::variant<bool, int, const char*>;

struct BackendOption {
const char* key; // key is the name of the backend option, like num_threads,
// enable_profiling, etc
OptionValue
value; // value is the value of the backend option, like 4, true, etc
};

template <size_t MaxCapacity>
class BackendOptions {
public:
// Initialize with zero options
BackendOptions() : size_(0) {}

// Type-safe setters
template <typename T>
void set_option(OptionKey<T> key, T value) {
const char* k = key.key;
// Update existing if found
for (size_t i = 0; i < size_; ++i) {
if (strcmp(options_[i].key, k) == 0) {
options_[i].value = value;
return;
}
}
// Add new option if space available
if (size_ < MaxCapacity) {
options_[size_++] = BackendOption{k, value};
}
}

// Type-safe getters
template <typename T>
Error get_option(OptionKey<T> key, T& out) const {
const char* k = key.key;
for (size_t i = 0; i < size_; ++i) {
if (strcmp(options_[i].key, k) == 0) {
if (auto* val = std::get_if<T>(&options_[i].value)) {
out = *val;
return Error::Ok;
}
return Error::InvalidArgument;
}
}
return Error::NotFound;
}
executorch::runtime::ArrayRef<BackendOption> view() const {
return executorch::runtime::ArrayRef<BackendOption>(options_, size_);
}

private:
BackendOption options_[MaxCapacity]{}; // Storage for backend options
size_t size_; // Current number of options
};

// Helper functions for creating typed option keys (unchanged)
constexpr OptionKey<bool> BoolKey(const char* k) {
return OptionKey<bool>(k);
}

constexpr OptionKey<int> IntKey(const char* k) {
return OptionKey<int>(k);
}

constexpr OptionKey<const char*> StrKey(const char* k) {
return OptionKey<const char*>(k);
}

} // namespace runtime
} // namespace executorch

#pragma once
#include <executorch/runtime/core/array_ref.h>
#include <executorch/runtime/core/error.h>
#include <cstddef>
#include <cstring>
#include <variant>

namespace executorch {
namespace runtime {

// Strongly-typed option key template
template <typename T>
struct OptionKey {
const char* key;
constexpr explicit OptionKey(const char* k) : key(k) {}
};

// Union replaced with std::variant
using OptionValue = std::variant<bool, int, const char*>;

struct BackendOption {
const char* key; // key is the name of the backend option, like num_threads,
// enable_profiling, etc
OptionValue
value; // value is the value of the backend option, like 4, true, etc
};

template <size_t MaxCapacity>
class BackendOptions {
public:
// Initialize with zero options
BackendOptions() : size_(0) {}

// Type-safe setters
template <typename T>
void set_option(OptionKey<T> key, T value) {
const char* k = key.key;
// Update existing if found
for (size_t i = 0; i < size_; ++i) {
if (strcmp(options_[i].key, k) == 0) {
options_[i].value = value;
return;
}
}
// Add new option if space available
if (size_ < MaxCapacity) {
options_[size_++] = BackendOption{k, value};
}
}

// Type-safe getters
template <typename T>
Error get_option(OptionKey<T> key, T& out) const {
const char* k = key.key;
for (size_t i = 0; i < size_; ++i) {
if (strcmp(options_[i].key, k) == 0) {
if (auto* val = std::get_if<T>(&options_[i].value)) {
out = *val;
return Error::Ok;
}
return Error::InvalidArgument;
}
}
return Error::NotFound;
}
executorch::runtime::ArrayRef<BackendOption> view() const {
return executorch::runtime::ArrayRef<BackendOption>(options_, size_);
}

private:
BackendOption options_[MaxCapacity]{}; // Storage for backend options
size_t size_; // Current number of options
};

// Helper functions for creating typed option keys (unchanged)
constexpr OptionKey<bool> BoolKey(const char* k) {
return OptionKey<bool>(k);
}

constexpr OptionKey<int> IntKey(const char* k) {
return OptionKey<int>(k);
}

constexpr OptionKey<const char*> StrKey(const char* k) {
return OptionKey<const char*>(k);
}

} // namespace runtime
} // namespace executorch
74 changes: 74 additions & 0 deletions runtime/backend/backend_options_map.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree.
*/

#include <executorch/runtime/backend/backend_options.h>
#include <executorch/runtime/core/error.h>
#include <cstring>

#pragma once
namespace executorch {
namespace runtime {

struct Entry {
const char* backend_name;
ArrayRef<BackendOption> options;
};

template <size_t MaxBackends>
class BackendOptionsMap {
public:
// Default constructor
BackendOptionsMap() : size_(0) {}

// Add a new backend configuration
Error add(
const char* backend_name,
::executorch::runtime::ArrayRef<BackendOption> options) {
if (size_ < MaxBackends) {
entries_[size_] = {backend_name, options};
++size_;
return Error::Ok;
} else {
ET_LOG(Error, "Maximum number of backends %lu reached", MaxBackends);
}
return Error::InvalidArgument;
}

// Get options for a specific backend
::executorch::runtime::ArrayRef<BackendOption> get(
const char* backend_name) const {
for (size_t i = 0; i < size_; ++i) {
if (std::strcmp(entries_[i].backend_name, backend_name) == 0) {
return entries_[i].options;
}
}
return {}; // Return empty ArrayRef if not found
}

// Get a view of the entries (const version)
::executorch::runtime::ArrayRef<const Entry> entries() const {
return ::executorch::runtime::ArrayRef<const Entry>(entries_, size_);
}

// Get a view of the entries (non-const version)
::executorch::runtime::ArrayRef<Entry> entries() {
return ::executorch::runtime::ArrayRef<Entry>(entries_, size_);
}

// Get number of entries
size_t size() const {
return size_;
}

private:
Entry entries_[MaxBackends]; // Storage for backend entries
size_t size_ = 0; // Current number of entries
};

} // namespace runtime
} // namespace executorch
37 changes: 36 additions & 1 deletion runtime/backend/targets.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ def define_common_targets():

for aten_mode in get_aten_mode_options():
aten_suffix = ("_aten" if aten_mode else "")
runtime.cxx_library(
name = "backend_options" + aten_suffix,
exported_headers = [
"backend_options.h",
],
preprocessor_flags = ["-DUSE_ATEN_LIB"] if aten_mode else [],
visibility = [
"//executorch/...",
"@EXECUTORCH_CLIENTS",
],
exported_deps = [
"//executorch/runtime/core:core",
"//executorch/runtime/core:evalue" + aten_suffix,
"//executorch/runtime/core:event_tracer" + aten_suffix,
"//executorch/runtime/core:memory_allocator",
"//executorch/runtime/core:named_data_map",
],
)

runtime.cxx_library(
name = "interface" + aten_suffix,
srcs = [
Expand All @@ -18,7 +37,6 @@ def define_common_targets():
"backend_execution_context.h",
"backend_init_context.h",
"backend_update_context.h",
"backend_options.h",
"interface.h",
],
preprocessor_flags = ["-DUSE_ATEN_LIB"] if aten_mode else [],
Expand All @@ -32,5 +50,22 @@ def define_common_targets():
"//executorch/runtime/core:event_tracer" + aten_suffix,
"//executorch/runtime/core:memory_allocator",
"//executorch/runtime/core:named_data_map",
"//executorch/runtime/backend:backend_options" + aten_suffix,
],
)

runtime.cxx_library(
name = "backend_options_map" + aten_suffix,
exported_headers = [
"backend_options_map.h",
],
preprocessor_flags = ["-DUSE_ATEN_LIB"] if aten_mode else [],
visibility = [
"//executorch/...",
"@EXECUTORCH_CLIENTS",
],
exported_deps = [
"//executorch/runtime/core:core",
":backend_options" + aten_suffix,
],
)
Loading
Loading