Skip to content
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d5a5295
Introduce public MergedDataMap
lucylq Oct 3, 2025
a00bab7
Update on "Introduce public MergedDataMap"
lucylq Oct 3, 2025
3aad6a9
Update on "Introduce public MergedDataMap"
lucylq Oct 3, 2025
a9c4c55
Update on "Introduce public MergedDataMap"
lucylq Oct 3, 2025
3843756
Update on "Introduce public MergedDataMap"
lucylq Oct 3, 2025
f19b922
Update on "Introduce public MergedDataMap"
lucylq Oct 3, 2025
cb5f30d
Update on "Introduce public MergedDataMap"
lucylq Oct 3, 2025
e2592ae
Update on "Introduce public MergedDataMap"
lucylq Oct 4, 2025
041a65a
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
a79a486
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
4896344
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
75ebd26
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
bae6c44
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
8f475c1
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
4fe31ba
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
47383bf
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
9f1378c
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
53faa4a
Update on "Introduce public MergedDataMap"
lucylq Oct 6, 2025
836dc33
Update on "Introduce public MergedDataMap"
lucylq Oct 7, 2025
29778bd
Update on "Introduce public MergedDataMap"
lucylq Oct 7, 2025
d93fbb9
Update on "Introduce public MergedDataMap"
lucylq Oct 7, 2025
ef0d885
Update on "Introduce public MergedDataMap"
lucylq Oct 7, 2025
076102f
Update on "Introduce public MergedDataMap"
lucylq Oct 7, 2025
2499d6c
Update on "Introduce public MergedDataMap"
lucylq Oct 7, 2025
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
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -630,6 +630,11 @@ if(EXECUTORCH_BUILD_EXTENSION_MODULE)
list(APPEND _executorch_extensions extension_module_static)
endif()

if(EXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP)
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/extension/named_data_map)
list(APPEND _executorch_extensions extension_named_data_map)
endif()

if(EXECUTORCH_BUILD_EXTENSION_LLM)
if(EXECUTORCH_BUILD_EXTENSION_LLM_RUNNER)
set(SUPPORT_REGEX_LOOKAHEAD ON)
Expand Down
1 change: 1 addition & 0 deletions backends/mediatek/scripts/mtk_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cmake -DCMAKE_INSTALL_PREFIX="${build_dir}" \
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON \
-DEXECUTORCH_BUILD_NEURON=ON \
-B"${build_dir}"

Expand Down
2 changes: 2 additions & 0 deletions backends/qualcomm/scripts/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ if [ "$BUILD_AARCH64" = true ]; then
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON \
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
-DEXECUTORCH_ENABLE_EVENT_TRACER=ON \
-DEXECUTORCH_ENABLE_LOGGING=ON \
Expand Down Expand Up @@ -155,6 +156,7 @@ if [ "$BUILD_X86_64" = true ]; then
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON \
-DEXECUTORCH_BUILD_KERNELS_QUANTIZED=ON \
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
-DEXECUTORCH_ENABLE_EVENT_TRACER=ON \
Expand Down
2 changes: 2 additions & 0 deletions backends/samsung/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function build_x86_64() {
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON \
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
-S ${PROJECT_DIR} \
-B ${X86_64_BUILD_DIR}
Expand Down Expand Up @@ -77,6 +78,7 @@ function build_android() {
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON \
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
-DEXECUTORCH_ENABLE_LOGGING=1 \
-DEXECUTORCH_BUILD_DEVTOOLS=ON \
Expand Down
1 change: 1 addition & 0 deletions backends/vulkan/test/scripts/test_model.sh
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ build_core_libraries_and_devtools() {
-DEXECUTORCH_BUILD_EXTENSION_DATA_LOADER=ON \
-DEXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR=ON \
-DEXECUTORCH_BUILD_EXTENSION_MODULE=ON \
-DEXECUTORCH_BUILD_EXTENSION_NAMED_DATA_MAP=ON \
-DEXECUTORCH_BUILD_EXTENSION_RUNNER_UTIL=ON \
-DEXECUTORCH_BUILD_EXTENSION_TENSOR=ON \
-DEXECUTORCH_BUILD_EXECUTOR_RUNNER=ON \
Expand Down
46 changes: 46 additions & 0 deletions extension/named_data_map/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# 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.

# Please this file formatted by running:
# ~~~
# cmake-format -i CMakeLists.txt
# ~~~

cmake_minimum_required(VERSION 3.19)

# Source root directory for executorch.
if(NOT EXECUTORCH_ROOT)
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
endif()

list(TRANSFORM _extension_named_data_map__srcs PREPEND "${EXECUTORCH_ROOT}/")
# Create the library
add_library(extension_named_data_map ${_extension_named_data_map__srcs})

# Link dependencies
target_link_libraries(extension_named_data_map PUBLIC executorch_core)

target_include_directories(
extension_named_data_map PUBLIC ${_common_include_directories}
)

target_compile_options(
extension_named_data_map PUBLIC ${_common_compile_options}
)

# Install libraries
install(
TARGETS extension_named_data_map
EXPORT ExecuTorchTargets
DESTINATION lib
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should be CMAKE_INSTALL_LIBDIR from GNUInstallDirs; inconveniently I never landed #12792 so we have a bunch of bad examples laying around

INCLUDES
DESTINATION ${_common_include_directories}
)

# Add tests if testing is enabled
if(BUILD_TESTING)
add_subdirectory(test)
endif()
8 changes: 8 additions & 0 deletions extension/named_data_map/TARGETS
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Any targets that should be shared between fbcode and xplat must be defined in
# targets.bzl. This file can contain fbcode-only targets.

load(":targets.bzl", "define_common_targets")

oncall("executorch")

define_common_targets()
117 changes: 117 additions & 0 deletions extension/named_data_map/merged_data_map.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* 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/extension/named_data_map/merged_data_map.h>
#include <executorch/runtime/core/data_loader.h>

#include <unordered_map>
#include <vector>

using executorch::aten::string_view;
using executorch::ET_RUNTIME_NAMESPACE::NamedDataMap;
using executorch::ET_RUNTIME_NAMESPACE::TensorLayout;
using executorch::runtime::Error;
using executorch::runtime::FreeableBuffer;
using executorch::runtime::Result;
using executorch::runtime::Span;

namespace executorch::extension {

/*static*/ Result<MergedDataMap> MergedDataMap::load(
Span<const NamedDataMap*> named_data_maps) {
std::vector<const NamedDataMap*> valid_data_maps;
for (auto i : c10::irange(named_data_maps.size())) {
if (named_data_maps[i] != nullptr &&
named_data_maps[i]->get_num_keys().get() > 0) {
valid_data_maps.push_back(named_data_maps[i]);
}
}
ET_CHECK_OR_RETURN_ERROR(
!valid_data_maps.empty(),
InvalidArgument,
"No non-empty named data maps provided to merge");

// Check for duplicate keys.
std::unordered_map<std::string, uint32_t> key_to_map_index;
for (uint32_t i = 0; i < valid_data_maps.size(); i++) {
const auto cur_map = valid_data_maps[i];
uint32_t num_keys = cur_map->get_num_keys().get();
for (uint32_t j = 0; j < num_keys; ++j) {
const auto cur_key = cur_map->get_key(j).get();
const auto [it, inserted] = key_to_map_index.emplace(cur_key, i);
ET_CHECK_OR_RETURN_ERROR(
inserted,
InvalidArgument,
"Duplicate key %s in named data maps at index %u and %u",
cur_key,
it->second,
i);
}
}
return MergedDataMap(std::move(valid_data_maps), std::move(key_to_map_index));
}

ET_NODISCARD Result<const TensorLayout> MergedDataMap::get_tensor_layout(
string_view key) const {
const auto it = key_to_map_index_.find(key.data());
ET_CHECK_OR_RETURN_ERROR(
it != key_to_map_index_.end(),
NotFound,
"Key %s not found in named data maps",
key.data());

return named_data_maps_.at(it->second)->get_tensor_layout(key);
}

ET_NODISCARD
Result<FreeableBuffer> MergedDataMap::get_data(string_view key) const {
const auto it = key_to_map_index_.find(key.data());
ET_CHECK_OR_RETURN_ERROR(
it != key_to_map_index_.end(),
NotFound,
"Key %s not found in named data maps",
key.data());
return named_data_maps_.at(it->second)->get_data(key);
}

ET_NODISCARD Error MergedDataMap::load_data_into(
string_view key,
void* buffer,
size_t size) const {
const auto it = key_to_map_index_.find(key.data());
ET_CHECK_OR_RETURN_ERROR(
it != key_to_map_index_.end(),
NotFound,
"Key %s not found in named data maps",
key.data());
return named_data_maps_.at(it->second)->load_data_into(key, buffer, size);
}

ET_NODISCARD Result<uint32_t> MergedDataMap::get_num_keys() const {
return key_to_map_index_.size();
}

ET_NODISCARD Result<const char*> MergedDataMap::get_key(uint32_t index) const {
uint32_t total_num_keys = get_num_keys().get();
ET_CHECK_OR_RETURN_ERROR(
index < total_num_keys,
InvalidArgument,
"Index %u out of range of size %u",
index,
total_num_keys);
for (auto i : c10::irange(named_data_maps_.size())) {
auto num_keys = named_data_maps_[i]->get_num_keys().get();
if (index < num_keys) {
return named_data_maps_[i]->get_key(index);
}
index -= num_keys;
}
// Shouldn't reach here.
return Error::Internal;
}
} // namespace executorch::extension
108 changes: 108 additions & 0 deletions extension/named_data_map/merged_data_map.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/*
* 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.
*/

#pragma once

#include <executorch/runtime/core/named_data_map.h>

#include <unordered_map>
#include <vector>

namespace executorch {
namespace extension {
/**
* A NamedDataMap implementation that wraps other NamedDataMaps.
*/
class MergedDataMap final
: public executorch::ET_RUNTIME_NAMESPACE::NamedDataMap {
public:
/**
* Creates a new NamedDataMap that takes in other data maps.
*
* @param[in] data_maps vector of NamedDataMap pointers to merge.
* Note: the data maps must outlive the MergedDataMap instance.
*/
static executorch::runtime::Result<MergedDataMap>
load(executorch::runtime::Span<
const executorch::ET_RUNTIME_NAMESPACE::NamedDataMap*> named_data_maps);

/**
* Retrieve the tensor_layout for the specified key.
*
* @param[in] key The name of the tensor to get metadata on.
*
* @return Error::NotFound if the key is not present.
*/
ET_NODISCARD
executorch::runtime::Result<
const executorch::ET_RUNTIME_NAMESPACE::TensorLayout>
get_tensor_layout(executorch::aten::string_view key) const override;

/**
* Retrieve read-only data for the specified key.
*
* @param[in] key The name of the tensor to get data on.
*
* @return error if the key is not present or data cannot be loaded.
*/
ET_NODISCARD
executorch::runtime::Result<executorch::runtime::FreeableBuffer> get_data(
executorch::aten::string_view key) const override;

/**
* Loads the data of the specified tensor into the provided buffer.
*
* @param[in] key The name of the tensor to get the data of.
* @param[in] buffer The buffer to load data into. Must point to at least
* `size` bytes of memory.
* @param[in] size The number of bytes to load.
*
* @returns an Error indicating if the load was successful.
*/
ET_NODISCARD executorch::runtime::Error load_data_into(
executorch::aten::string_view key,
void* buffer,
size_t size) const override;

/**
* @returns The number of keys in the map.
*/
ET_NODISCARD executorch::runtime::Result<uint32_t> get_num_keys()
const override;
/**
* @returns The key at the specified index, error if index out of bounds.
*/
ET_NODISCARD executorch::runtime::Result<const char*> get_key(
uint32_t index) const override;

MergedDataMap(MergedDataMap&&) noexcept = default;

~MergedDataMap() override = default;

private:
MergedDataMap(
std::vector<const executorch::ET_RUNTIME_NAMESPACE::NamedDataMap*>
named_data_maps,
std::unordered_map<std::string, uint32_t> key_to_map_index)
: named_data_maps_(std::move(named_data_maps)),
key_to_map_index_(std::move(key_to_map_index)) {}

// Not copyable or assignable.
MergedDataMap(const MergedDataMap& rhs) = delete;
MergedDataMap& operator=(MergedDataMap&& rhs) noexcept = delete;
MergedDataMap& operator=(const MergedDataMap& rhs) = delete;

std::vector<const executorch::ET_RUNTIME_NAMESPACE::NamedDataMap*>
named_data_maps_;

// Map from key to index in the named_data_maps_ vector.
std::unordered_map<std::string, uint32_t> key_to_map_index_;
};

} // namespace extension
} // namespace executorch
21 changes: 21 additions & 0 deletions extension/named_data_map/targets.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
load("@fbsource//xplat/executorch/build:runtime_wrapper.bzl", "get_aten_mode_options", "runtime")

def define_common_targets():
for aten_mode in get_aten_mode_options():
aten_suffix = "_aten" if aten_mode else ""
runtime.cxx_library(
name = "merged_data_map" + aten_suffix,
srcs = [
"merged_data_map.cpp",
],
exported_headers = [
"merged_data_map.h",
],
visibility = [
"@EXECUTORCH_CLIENTS",
],
deps = [
"//executorch/runtime/core:named_data_map",
"//executorch/runtime/core:core",
],
)
Loading
Loading