Skip to content
Merged
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
6 changes: 3 additions & 3 deletions extension/flat_tensor/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ include(${EXECUTORCH_ROOT}/build/Test.cmake)

add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.pte"
"${CMAKE_CURRENT_BINARY_DIR}/_default_external_constant.ptd"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.ptd"
COMMAND
python -m test.models.export_program --modules "ModuleLinear"
--external-constants --outdir "${CMAKE_CURRENT_BINARY_DIR}" 2> /dev/null
Expand All @@ -30,12 +30,12 @@ add_custom_command(
add_custom_target(
extension_flat_tensor_test_resources
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.pte"
"${CMAKE_CURRENT_BINARY_DIR}/_default_external_constant.ptd"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.ptd"
)

set(test_env
"ET_MODULE_LINEAR_PROGRAM_PATH=${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.pte"
"ET_MODULE_LINEAR_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}/_default_external_constant.ptd"
"ET_MODULE_LINEAR_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.ptd"
)

set(_test_srcs flat_tensor_data_map_test.cpp flat_tensor_header_test.cpp)
Expand Down
7 changes: 5 additions & 2 deletions extension/training/module/test/targets.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ def define_common_targets(is_fbcode = False):
# an fbcode target path because the authoring/export tools
# intentionally don't work in xplat (since they're host-only tools).
"ET_MODULE_ADD_PATH": "$(location fbcode//executorch/test/models:exported_programs[ModuleAdd.pte])",
"ET_MODULE_SIMPLE_TRAIN_PATH": "$(location fbcode//executorch/test/models:exported_programs[ModuleSimpleTrain.pte])",
"ET_MODULE_LINEAR_PROGRAM_PATH": "$(location fbcode//executorch/test/models:exported_program_and_data[ModuleLinear.pte])",
"ET_MODULE_LINEAR_DATA_PATH": "$(location fbcode//executorch/test/models:exported_program_and_data[ModuleLinear.ptd])",
"ET_MODULE_LINEAR_PROGRAM_PATH": "$(location fbcode//executorch/test/models:exported_program_and_data[ModuleLinear.pte])",
"ET_MODULE_TRAIN_DATA_PATH": "$(location fbcode//executorch/test/models:exported_program_and_data[ModuleSimpleTrain.ptd])",
"ET_MODULE_TRAIN_PROGRAM_PATH": "$(location fbcode//executorch/test/models:exported_program_and_data[ModuleSimpleTrainProgram.pte])",
"ET_MODULE_SIMPLE_TRAIN_PATH": "$(location fbcode//executorch/test/models:exported_programs[ModuleSimpleTrain.pte])",
}

runtime.cxx_test(
Expand All @@ -29,6 +31,7 @@ def define_common_targets(is_fbcode = False):
deps = [
"//executorch/extension/training/module:training_module",
"//executorch/extension/data_loader:file_data_loader",
"//executorch/extension/flat_tensor:flat_tensor_data_map",
"//executorch/runtime/core/exec_aten/testing_util:tensor_util",
"//executorch/kernels/portable:generated_lib",
],
Expand Down
48 changes: 48 additions & 0 deletions extension/training/module/test/training_module_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

#include <executorch/extension/data_loader/file_data_loader.h>
#include <executorch/extension/flat_tensor/flat_tensor_data_map.h>
#include <executorch/extension/training/module/training_module.h>

#include <executorch/runtime/core/exec_aten/testing_util/tensor_factory.h>
Expand All @@ -18,9 +19,17 @@
using namespace ::testing;
using executorch::aten::ScalarType;
using executorch::aten::Tensor;
using executorch::extension::FlatTensorDataMap;
using executorch::extension::FlatTensorHeader;
using executorch::runtime::DataLoader;
using executorch::runtime::Error;
using executorch::runtime::FreeableBuffer;
using executorch::runtime::Result;
using executorch::runtime::TensorLayout;
using torch::executor::Error;
using torch::executor::Span;
using torch::executor::testing::TensorFactory;
using torch::executor::util::FileDataLoader;

class TrainingModuleTest : public ::testing::Test {
protected:
Expand Down Expand Up @@ -105,3 +114,42 @@ TEST_F(TrainingModuleTest, NonTrainingModuleTest) {
auto res = mod.execute_forward_backward("forward", inputs);
ASSERT_EQ(res.error(), Error::InvalidArgument);
}

TEST_F(TrainingModuleTest, SeperateDataTest) {
// Load data map.
// The eager linear model is defined at:
// //executorch/test/models/linear_model.py
const char* ptd_path = std::getenv("ET_MODULE_TRAIN_DATA_PATH");
Result<FileDataLoader> data_map_loader_res = FileDataLoader::from(ptd_path);
ASSERT_EQ(data_map_loader_res.error(), Error::Ok);

auto data_map_loader =
std::make_unique<torch::executor::util::FileDataLoader>(
std::move(data_map_loader_res.get()));

const char* pte_path = std::getenv("ET_MODULE_TRAIN_PROGRAM_PATH");
Result<FileDataLoader> pte_loader_res = FileDataLoader::from(pte_path);
ASSERT_EQ(pte_loader_res.error(), Error::Ok);

auto pte_loader = std::make_unique<torch::executor::util::FileDataLoader>(
std::move(pte_loader_res.get()));

auto mod = executorch::extension::training::TrainingModule(
std::move(pte_loader),
nullptr,
nullptr,
nullptr,
std::move(data_map_loader));

TensorFactory<ScalarType::Float> tf;
Tensor input = tf.make({3}, {1.0, 1.0, 1.0});
Tensor label = tf.make({3}, {1.0, 0.0, 0.0});

std::vector<executorch::runtime::EValue> inputs;
inputs.push_back(input);
inputs.push_back(label);

auto res = mod.execute_forward_backward("forward", inputs);
ASSERT_EQ(res.error(), Error::Ok);
ASSERT_EQ(res.get().size(), 1);
}
81 changes: 45 additions & 36 deletions extension/training/module/training_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ TrainingModule::execute_forward_backward(
uint64_t param_start = param_res.get()[0].toInt();

// Execute the forward and backward pass.

auto outputs = torch::executor::Module::execute(method_name, input);
if (!outputs.ok()) {
return outputs.error();
Expand All @@ -56,19 +55,23 @@ TrainingModule::execute_forward_backward(
user_outputs.push_back(outputs.get().at(i));
}

// Extract and store the gradients.
// Extract and store the gradients and params if this is the first time seeing
// this method.
if (method_named_gradients_.find(method_name) ==
method_named_gradients_.end()) {
// Fully qualified names
std::vector<runtime::EValue> fqn_list;
method_named_gradients_.insert({method_name, {}});

auto& gradients_map = method_named_gradients_.at(method_name);
// Get names.

// Get names if we havent seen this method before.
const std::string fqn_method_name = fqn_method_prefix + method_name;
auto fqn_res = executorch::extension::Module::execute(fqn_method_name);
if (!fqn_res.ok()) {
return fqn_res.error();
}
const auto& fqn_list = fqn_res.get();
fqn_list = fqn_res.get();

// Only have to initialize the dict once because the tensors in the dict and
// the tensors in the method alias the same TensorImpl, so updating one will
Expand All @@ -87,43 +90,49 @@ TrainingModule::execute_forward_backward(
runtime::Result<
const std::map<executorch::aten::string_view, executorch::aten::Tensor>>
TrainingModule::named_parameters(const std::string& method_name) {
std::map<executorch::aten::string_view, executorch::aten::Tensor>
named_parameters;
const std::string fqn_method_name = fqn_method_prefix + method_name;
const std::string parameters_method_name =
parameters_method_prefix + method_name;
// If we haven't seen this method before, populate the dict.
if (method_named_parameters_.find(method_name) ==
method_named_parameters_.end()) {
const std::string fqn_method_name = fqn_method_prefix + method_name;
const std::string parameters_method_name =
parameters_method_prefix + method_name;

// get names.
auto fqn_res = executorch::extension::Module::execute(fqn_method_name);
if (!fqn_res.ok()) {
return fqn_res.error();
}
const auto& fqn_list = fqn_res.get();
method_named_parameters_.insert({method_name, {}});

// get params start.
auto param_res =
executorch::extension::Module::execute(parameters_method_name);
if (!param_res.ok()) {
return param_res.error();
}
// get names.
auto fqn_res = executorch::extension::Module::execute(fqn_method_name);
if (!fqn_res.ok()) {
return fqn_res.error();
}
const auto& fqn_list = fqn_res.get();

uint64_t param_start = param_res.get()[0].toInt();
// get params start.
auto param_res =
executorch::extension::Module::execute(parameters_method_name);
if (!param_res.ok()) {
return param_res.error();
}

auto e = executorch::extension::Module::load_method(method_name);
if (e != runtime::Error::Ok) {
return e;
}
auto& method = methods_.at(method_name).method;

// create dict
size_t name_index = 0;
for (size_t param_index = param_start; param_index < method->outputs_size();
++param_index, ++name_index) {
executorch::aten::string_view fqn = fqn_list.at(name_index).toString();
executorch::aten::Tensor param = method->get_output(param_index).toTensor();
named_parameters.insert({fqn, param});
uint64_t param_start = param_res.get()[0].toInt();

// Load the method if it is not already loaded.
auto e = executorch::extension::Module::load_method(method_name);
if (e != runtime::Error::Ok) {
return e;
}
auto& method = methods_.at(method_name).method;

// populate dict
size_t name_index = 0;
for (size_t param_index = param_start; param_index < method->outputs_size();
++param_index, ++name_index) {
executorch::aten::string_view fqn = fqn_list.at(name_index).toString();
executorch::aten::Tensor param =
method->get_output(param_index).toTensor();
method_named_parameters_.at(method_name).insert({fqn, param});
}
}
return named_parameters;
return method_named_parameters_.at(method_name);
}

runtime::Result<
Expand Down
14 changes: 11 additions & 3 deletions extension/training/module/training_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,16 @@ class ET_EXPERIMENTAL TrainingModule final
std::unique_ptr<runtime::DataLoader> data_loader,
std::unique_ptr<runtime::MemoryAllocator> memory_allocator = nullptr,
std::unique_ptr<runtime::MemoryAllocator> temp_allocator = nullptr,
std::unique_ptr<runtime::EventTracer> event_tracer = nullptr)
std::unique_ptr<runtime::EventTracer> event_tracer = nullptr,
std::unique_ptr<runtime::DataLoader> data_map_data_loader = nullptr)
: executorch::extension::Module(
std::move(data_loader),
std::move(memory_allocator),
std::move(temp_allocator),
std::move(event_tracer)),
method_named_gradients_({}) {}
std::move(event_tracer),
std::move(data_map_data_loader)),
method_named_gradients_({}),
method_named_parameters_({}) {}

explicit TrainingModule(const Module&) = delete;
TrainingModule& operator=(const Module&) = delete;
Expand Down Expand Up @@ -97,6 +100,11 @@ class ET_EXPERIMENTAL TrainingModule final
std::string,
std::map<executorch::aten::string_view, executorch::aten::Tensor>>
method_named_gradients_;

std::unordered_map<
std::string,
std::map<executorch::aten::string_view, executorch::aten::Tensor>>
method_named_parameters_;
};

} // namespace training
Expand Down
37 changes: 17 additions & 20 deletions runtime/executor/tensor_parser_exec_aten.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,24 +169,8 @@ ET_NODISCARD Result<void*> getTensorDataPtr(
const executorch_flatbuffer::AllocationDetails* allocation_info =
s_tensor->allocation_info();

// Memory Planned, with initial state
if (data_buffer_idx > 0 && allocation_info != nullptr) {
auto planned_ptr = getMemPlannedPtr(allocation_info, nbytes, allocator);
if (!planned_ptr.ok()) {
return planned_ptr.error();
}
auto err = TensorParser::load_mutable_subsegment_into(
program, 0, s_tensor->data_buffer_idx(), nbytes, planned_ptr.get());

if (err != Error::Ok) {
return err;
}
return planned_ptr;
}

// External tensors.
else if (
s_tensor->extra_tensor_info() != nullptr &&
if (s_tensor->extra_tensor_info() != nullptr &&
s_tensor->extra_tensor_info()->location() ==
executorch_flatbuffer::TensorDataLocation::EXTERNAL) {
// Check that fqn is not null.
Expand Down Expand Up @@ -232,10 +216,9 @@ ET_NODISCARD Result<void*> getTensorDataPtr(

return planned_ptr;
}
}

// Constant, stored in PTE file.
else if (data_buffer_idx > 0 && allocation_info == nullptr) {
// Constant, stored in PTE file.
} else if (data_buffer_idx > 0 && allocation_info == nullptr) {
auto const_data =
program->get_constant_buffer_data(data_buffer_idx, nbytes);
if (!const_data.ok()) {
Expand All @@ -246,6 +229,20 @@ ET_NODISCARD Result<void*> getTensorDataPtr(
// guarantee that this data is never modified.
return const_cast<void*>(const_data.get());

// Memory Planned, with initial state
} else if (data_buffer_idx > 0 && allocation_info != nullptr) {
auto planned_ptr = getMemPlannedPtr(allocation_info, nbytes, allocator);
if (!planned_ptr.ok()) {
return planned_ptr.error();
}
auto err = TensorParser::load_mutable_subsegment_into(
program, 0, s_tensor->data_buffer_idx(), nbytes, planned_ptr.get());

if (err != Error::Ok) {
return err;
}
return planned_ptr;

// Memory planned, no initial state
} else if (data_buffer_idx == 0 && allocation_info != nullptr) {
return getMemPlannedPtr(allocation_info, nbytes, allocator);
Expand Down
6 changes: 3 additions & 3 deletions runtime/executor/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ add_custom_command(
"${CMAKE_CURRENT_BINARY_DIR}/ModuleIndex.pte"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleLinear.pte"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.pte"
"${CMAKE_CURRENT_BINARY_DIR}/_default_external_constant.ptd"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.ptd"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleMultipleEntry.pte"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleSimpleTrain.pte"
COMMAND
Expand All @@ -48,7 +48,7 @@ add_custom_target(
"${CMAKE_CURRENT_BINARY_DIR}/ModuleIndex.pte"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleLinear.pte"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.pte"
"${CMAKE_CURRENT_BINARY_DIR}/_default_external_constant.ptd"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.ptd"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleMultipleEntry.pte"
"${CMAKE_CURRENT_BINARY_DIR}/ModuleSimpleTrain.pte"
)
Expand All @@ -61,7 +61,7 @@ set(test_env
"ET_MODULE_INDEX_PATH=${CMAKE_CURRENT_BINARY_DIR}/ModuleIndex.pte"
"ET_MODULE_LINEAR_PATH=${CMAKE_CURRENT_BINARY_DIR}/ModuleLinear.pte"
"ET_MODULE_LINEAR_PROGRAM_PATH=${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.pte"
"ET_MODULE_LINEAR_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}/_default_external_constant.ptd"
"ET_MODULE_LINEAR_DATA_PATH=${CMAKE_CURRENT_BINARY_DIR}/ModuleLinearProgram.ptd"
"ET_MODULE_MULTI_ENTRY_PATH=${CMAKE_CURRENT_BINARY_DIR}/ModuleMultipleEntry.pte"
"ET_MODULE_SIMPLE_TRAIN_PATH=${CMAKE_CURRENT_BINARY_DIR}/ModuleSimpleTrain.pte"
)
Expand Down
5 changes: 5 additions & 0 deletions test/models/export_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ def main() -> None:
prog.write_to_file(fp)
print(f"Exported {module_name} and wrote program data to {outfile}")

if args.external_constants:
# current infra doesnt easily allow renaming this file, so just hackily do it here.
prog._tensor_data[f"{module_name}"] = prog._tensor_data.pop(
"_default_external_constant"
)
prog.write_tensor_data_to_file(args.outdir)


Expand Down
12 changes: 10 additions & 2 deletions test/models/targets.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,21 @@ def define_common_targets():
# case, and typically shouldn't be done.
_is_external_target = True,
)

# Class names of nn.Modules for :exported_programs to export.
MODULES_AND_DATA_TO_EXPORT = [
"ModuleLinear",
"ModuleSimpleTrain",
]

runtime.genrule(
name = "exported_program_and_data",
cmd = "$(exe :export_program) --modules ModuleLinear --external-constants --outdir $OUT",
cmd = "$(exe :export_program) --modules " + ",".join(MODULES_AND_DATA_TO_EXPORT) + " --external-constants --outdir $OUT",
outs = {
"ModuleLinear.pte": ["ModuleLinearProgram.pte"],
"ModuleLinear.ptd": ["_default_external_constant.ptd"],
"ModuleLinear.ptd": ["ModuleLinearProgram.ptd"],
"ModuleSimpleTrainProgram.pte": ["ModuleSimpleTrainProgram.pte"],
"ModuleSimpleTrain.ptd": ["ModuleSimpleTrainProgram.ptd"],
},
default_outs = ["."],
visibility = [
Expand Down
Loading