Skip to content

Commit 93d5a63

Browse files
committed
[pybinding] Add mapping from C++ program::verification to Python
Summary: As titled. This enables `portable_lib._load_for_executorch[_from_buffer]` to accept `Program::Verification` argument. See added test, now we can do something like: ``` from executorch.extension.pybindings.portable_lib import Verification module = load_fn( exported_program.buffer, enable_etdump=False, debug_buffer_size=0, load_program_config=Verification.Minimal, ) ``` Test Plan: See unit test Reviewers: Subscribers: Tasks: Tags:
1 parent 17c2f36 commit 93d5a63

File tree

3 files changed

+72
-18
lines changed

3 files changed

+72
-18
lines changed

extension/pybindings/portable_lib.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
_reset_profile_results, # noqa: F401
4646
BundledModule, # noqa: F401
4747
ExecuTorchModule, # noqa: F401
48+
Verification, # noqa: F401
4849
)
4950

5051
# Clean up so that `dir(portable_lib)` is the same as `dir(_portable_lib)`

extension/pybindings/pybindings.cpp

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -168,13 +168,14 @@ class Module final {
168168
explicit Module(
169169
std::unique_ptr<DataLoader> loader,
170170
std::unique_ptr<ETDumpGen> tracer = nullptr,
171-
size_t debug_buffer_size = 0)
171+
size_t debug_buffer_size = 0,
172+
Program::Verification load_program_config =
173+
Program::Verification::InternalConsistency)
172174
: loader_(std::move(loader)),
173175
event_tracer_(std::move(tracer)),
174176
debug_buffer_size_(debug_buffer_size) {
175177
::executorch::runtime::runtime_init();
176-
Result<Program> program = Program::load(
177-
loader_.get(), Program::Verification::InternalConsistency);
178+
Result<Program> program = Program::load(loader_.get(), load_program_config);
178179
THROW_IF_ERROR(
179180
program.error(),
180181
"loading program failed with error: 0x%" PRIx32,
@@ -388,19 +389,22 @@ inline std::unique_ptr<Module> load_module_from_buffer(
388389
const void* ptr,
389390
size_t ptr_len,
390391
bool enable_etdump,
391-
size_t debug_buffer_size) {
392+
size_t debug_buffer_size,
393+
Program::Verification load_program_config) {
392394
EXECUTORCH_SCOPE_PROF("load_module_from_buffer");
393395
auto loader = std::make_unique<BufferDataLoader>(ptr, ptr_len);
394396
return std::make_unique<Module>(
395397
std::move(loader),
396398
enable_etdump ? std::make_unique<torch::executor::ETDumpGen>() : nullptr,
397-
debug_buffer_size);
399+
debug_buffer_size,
400+
load_program_config);
398401
}
399402

400403
inline std::unique_ptr<Module> load_module_from_file(
401404
const std::string& path,
402405
bool enable_etdump,
403-
size_t debug_buffer_size) {
406+
size_t debug_buffer_size,
407+
Program::Verification load_program_config) {
404408
EXECUTORCH_SCOPE_PROF("load_module_from_file");
405409

406410
Result<MmapDataLoader> res = MmapDataLoader::from(
@@ -415,7 +419,8 @@ inline std::unique_ptr<Module> load_module_from_file(
415419
return std::make_unique<Module>(
416420
std::move(loader),
417421
enable_etdump ? std::make_unique<torch::executor::ETDumpGen>() : nullptr,
418-
debug_buffer_size);
422+
debug_buffer_size,
423+
load_program_config);
419424
}
420425

421426
static constexpr size_t kDEFAULT_BUNDLED_INPUT_POOL_SIZE = 16 * 1024U;
@@ -578,30 +583,41 @@ struct PyModule final {
578583
explicit PyModule(
579584
const py::bytes& buffer,
580585
bool enable_etdump,
581-
size_t debug_buffer_size = 0)
586+
size_t debug_buffer_size = 0,
587+
Program::Verification load_program_config =
588+
Program::Verification::InternalConsistency)
582589
: module_(load_module_from_buffer(
583590
buffer.cast<std::string_view>().data(),
584591
py::len(buffer),
585592
enable_etdump,
586-
debug_buffer_size)) {}
593+
debug_buffer_size,
594+
load_program_config)) {}
587595

588596
explicit PyModule(
589597
const void* ptr,
590598
size_t ptr_len,
591599
bool enable_etdump,
592-
size_t debug_buffer_size = 0)
600+
size_t debug_buffer_size = 0,
601+
Program::Verification load_program_config =
602+
Program::Verification::InternalConsistency)
593603
: module_(load_module_from_buffer(
594604
ptr,
595605
ptr_len,
596606
enable_etdump,
597-
debug_buffer_size)) {}
607+
debug_buffer_size,
608+
load_program_config)) {}
598609

599610
explicit PyModule(
600611
const std::string& path,
601612
bool enable_etdump,
602-
size_t debug_buffer_size = 0)
603-
: module_(load_module_from_file(path, enable_etdump, debug_buffer_size)) {
604-
}
613+
size_t debug_buffer_size = 0,
614+
Program::Verification load_program_config =
615+
Program::Verification::InternalConsistency)
616+
: module_(load_module_from_file(
617+
path,
618+
enable_etdump,
619+
debug_buffer_size,
620+
load_program_config)) {}
605621

606622
PyModule(const PyModule&) = delete;
607623
PyModule& operator=(const PyModule&) = delete;
@@ -612,14 +628,20 @@ struct PyModule final {
612628
static std::unique_ptr<PyModule> load_from_buffer(
613629
const py::bytes& buffer,
614630
bool enable_etdump,
615-
size_t debug_buffer_size = 0) {
616-
return std::make_unique<PyModule>(buffer, enable_etdump, debug_buffer_size);
631+
size_t debug_buffer_size = 0,
632+
Program::Verification load_program_config =
633+
Program::Verification::InternalConsistency) {
634+
return std::make_unique<PyModule>(
635+
buffer, enable_etdump, debug_buffer_size, load_program_config);
617636
}
618637
static std::unique_ptr<PyModule> load_from_file(
619638
const std::string& path,
620639
bool enable_etdump,
621-
size_t debug_buffer_size = 0) {
622-
return std::make_unique<PyModule>(path, enable_etdump, debug_buffer_size);
640+
size_t debug_buffer_size = 0,
641+
Program::Verification load_program_config =
642+
Program::Verification::InternalConsistency) {
643+
return std::make_unique<PyModule>(
644+
path, enable_etdump, debug_buffer_size, load_program_config);
623645
}
624646

625647
static std::unique_ptr<PyModule> load_from_bundled_program(
@@ -950,13 +972,17 @@ PYBIND11_MODULE(EXECUTORCH_PYTHON_MODULE_NAME, m) {
950972
py::arg("path"),
951973
py::arg("enable_etdump") = false,
952974
py::arg("debug_buffer_size") = 0,
975+
py::arg("load_program_config") =
976+
Program::Verification::InternalConsistency,
953977
call_guard);
954978
m.def(
955979
"_load_for_executorch_from_buffer",
956980
&PyModule::load_from_buffer,
957981
py::arg("buffer"),
958982
py::arg("enable_etdump") = false,
959983
py::arg("debug_buffer_size") = 0,
984+
py::arg("load_program_config") =
985+
Program::Verification::InternalConsistency,
960986
call_guard);
961987
m.def(
962988
"_load_for_executorch_from_bundled_program",
@@ -1065,6 +1091,10 @@ PYBIND11_MODULE(EXECUTORCH_PYTHON_MODULE_NAME, m) {
10651091
py::arg("index"),
10661092
call_guard)
10671093
.def("__repr__", &PyMethodMeta::repr, call_guard);
1094+
// Bind the verification enum to python.
1095+
py::enum_<Program::Verification>(m, "Verification")
1096+
.value("Minimal", Program::Verification::Minimal)
1097+
.value("InternalConsistency", Program::Verification::InternalConsistency);
10681098
}
10691099

10701100
} // namespace pybindings

extension/pybindings/test/make_test.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,28 @@ def test_bad_name(tester) -> None:
352352
with tester.assertRaises(RuntimeError):
353353
executorch_module.run_method("not_a_real_method", inputs)
354354

355+
def test_verification_config(tester) -> None:
356+
# Create an ExecuTorch program from ModuleAdd.
357+
exported_program, inputs = create_program(ModuleAdd())
358+
from executorch.extension.pybindings.portable_lib import Verification
359+
360+
# Use pybindings to load and execute the program.
361+
for config in [Verification.Minimal, Verification.InternalConsistency]:
362+
executorch_module = load_fn(
363+
exported_program.buffer,
364+
enable_etdump=False,
365+
debug_buffer_size=0,
366+
load_program_config=config,
367+
)
368+
369+
executorch_output = executorch_module.forward(inputs)[0]
370+
371+
# The test module adds the two inputs, so its output should be the same
372+
# as adding them directly.
373+
expected = inputs[0] + inputs[1]
374+
375+
tester.assertEqual(str(expected), str(executorch_output))
376+
355377
######### RUN TEST CASES #########
356378
test_e2e(tester)
357379
test_multiple_entry(tester)
@@ -363,5 +385,6 @@ def test_bad_name(tester) -> None:
363385
test_constant_output_not_memory_planned(tester)
364386
test_method_meta(tester)
365387
test_bad_name(tester)
388+
test_verification_config(tester)
366389

367390
return wrapper

0 commit comments

Comments
 (0)