Skip to content

Commit 179d495

Browse files
davidlin54lind
andauthored
[data loader] move logic for FD data loader out of file_data_loader (#6682)
move fd loader Co-authored-by: lind <[email protected]>
1 parent b4c6fe1 commit 179d495

File tree

10 files changed

+835
-202
lines changed

10 files changed

+835
-202
lines changed

examples/portable/executor_runner/executor_runner.cpp

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <unistd.h>
2727

2828
#include <executorch/extension/data_loader/file_data_loader.h>
29+
#include <executorch/extension/data_loader/file_descriptor_data_loader.h>
2930
#include <executorch/extension/evalue_util/print_evalue.h>
3031
#include <executorch/extension/runner_util/inputs.h>
3132
#include <executorch/runtime/executor/method.h>
@@ -45,6 +46,7 @@ DEFINE_bool(
4546
"True if the model_path passed is a file descriptor with the prefix \"fd:///\".");
4647

4748
using executorch::extension::FileDataLoader;
49+
using executorch::extension::FileDescriptorDataLoader;
4850
using executorch::runtime::Error;
4951
using executorch::runtime::EValue;
5052
using executorch::runtime::HierarchicalAllocator;
@@ -56,6 +58,33 @@ using executorch::runtime::Program;
5658
using executorch::runtime::Result;
5759
using executorch::runtime::Span;
5860

61+
static Result<Program> getProgram(
62+
const bool is_fd_uri,
63+
const char* model_path) {
64+
// Create a loader to get the data of the program file. This demonstrates both
65+
// FileDataLoader and FileDescriptorDataLoader. There are other DataLoaders
66+
// that use mmap() or point to data that's already in memory, and users can
67+
// create their own DataLoaders to load from arbitrary sources.
68+
if (!is_fd_uri) {
69+
Result<FileDataLoader> loader = FileDataLoader::from(model_path);
70+
71+
ET_CHECK_MSG(
72+
loader.ok(),
73+
"FileDataLoader::from() failed: 0x%" PRIx32,
74+
(uint32_t)loader.error());
75+
return Program::load(&loader.get());
76+
} else {
77+
Result<FileDescriptorDataLoader> loader =
78+
FileDescriptorDataLoader::fromFileDescriptorUri(model_path);
79+
80+
ET_CHECK_MSG(
81+
loader.ok(),
82+
"FileDescriptorDataLoader::fromFileDescriptorUri() failed: 0x%" PRIx32,
83+
(uint32_t)loader.error());
84+
return Program::load(&loader.get());
85+
}
86+
}
87+
5988
int main(int argc, char** argv) {
6089
executorch::runtime::runtime_init();
6190

@@ -75,18 +104,9 @@ int main(int argc, char** argv) {
75104
const char* model_path = FLAGS_model_path.c_str();
76105
const bool is_fd_uri = FLAGS_is_fd_uri;
77106

78-
Result<FileDataLoader> loader = is_fd_uri
79-
? FileDataLoader::fromFileDescriptorUri(model_path)
80-
: FileDataLoader::from(model_path);
81-
82-
ET_CHECK_MSG(
83-
loader.ok(),
84-
"FileDataLoader::from() failed: 0x%" PRIx32,
85-
(uint32_t)loader.error());
86-
87107
// Parse the program file. This is immutable, and can also be reused between
88108
// multiple execution invocations across multiple threads.
89-
Result<Program> program = Program::load(&loader.get());
109+
Result<Program> program = getProgram(is_fd_uri, model_path);
90110
if (!program.ok()) {
91111
ET_LOG(Error, "Failed to parse model file %s", model_path);
92112
return 1;

examples/portable/executor_runner/targets.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ def define_common_targets():
1515
deps = [
1616
"//executorch/runtime/executor:program",
1717
"//executorch/extension/data_loader:file_data_loader",
18+
"//executorch/extension/data_loader:file_descriptor_data_loader",
1819
"//executorch/extension/evalue_util:print_evalue",
1920
"//executorch/extension/runner_util:inputs",
2021
],

extension/data_loader/file_data_loader.cpp

Lines changed: 15 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,6 @@ namespace extension {
4343

4444
namespace {
4545

46-
static constexpr char kFdFilesystemPrefix[] = "fd:///";
47-
4846
/**
4947
* Returns true if the value is an integer power of 2.
5048
*/
@@ -76,36 +74,25 @@ FileDataLoader::~FileDataLoader() {
7674
::close(fd_);
7775
}
7876

79-
static Result<int> getFDFromUri(const char* file_descriptor_uri) {
80-
// check if the uri starts with the prefix "fd://"
77+
Result<FileDataLoader> FileDataLoader::from(
78+
const char* file_name,
79+
size_t alignment) {
8180
ET_CHECK_OR_RETURN_ERROR(
82-
strncmp(
83-
file_descriptor_uri,
84-
kFdFilesystemPrefix,
85-
strlen(kFdFilesystemPrefix)) == 0,
81+
is_power_of_2(alignment),
8682
InvalidArgument,
87-
"File descriptor uri (%s) does not start with %s",
88-
file_descriptor_uri,
89-
kFdFilesystemPrefix);
90-
91-
// strip "fd:///" from the uri
92-
int fd_len = strlen(file_descriptor_uri) - strlen(kFdFilesystemPrefix);
93-
char fd_without_prefix[fd_len + 1];
94-
memcpy(
95-
fd_without_prefix,
96-
&file_descriptor_uri[strlen(kFdFilesystemPrefix)],
97-
fd_len);
98-
fd_without_prefix[fd_len] = '\0';
83+
"Alignment %zu is not a power of 2",
84+
alignment);
9985

100-
// check if remaining fd string is a valid integer
101-
int fd = ::atoi(fd_without_prefix);
102-
return fd;
103-
}
86+
// Use open() instead of fopen() to avoid the layer of buffering that
87+
// fopen() does. We will be reading large portions of the file in one shot,
88+
// so buffering does not help.
89+
int fd = ::open(file_name, O_RDONLY);
90+
if (fd < 0) {
91+
ET_LOG(
92+
Error, "Failed to open %s: %s (%d)", file_name, strerror(errno), errno);
93+
return Error::AccessFailed;
94+
}
10495

105-
Result<FileDataLoader> FileDataLoader::fromFileDescriptor(
106-
const char* file_name,
107-
const int fd,
108-
size_t alignment) {
10996
// Cache the file size.
11097
struct stat st;
11198
int err = ::fstat(fd, &st);
@@ -132,47 +119,6 @@ Result<FileDataLoader> FileDataLoader::fromFileDescriptor(
132119
return FileDataLoader(fd, file_size, alignment, file_name_copy);
133120
}
134121

135-
Result<FileDataLoader> FileDataLoader::fromFileDescriptorUri(
136-
const char* file_descriptor_uri,
137-
size_t alignment) {
138-
ET_CHECK_OR_RETURN_ERROR(
139-
is_power_of_2(alignment),
140-
InvalidArgument,
141-
"Alignment %zu is not a power of 2",
142-
alignment);
143-
144-
auto parsed_fd = getFDFromUri(file_descriptor_uri);
145-
if (!parsed_fd.ok()) {
146-
return parsed_fd.error();
147-
}
148-
149-
int fd = parsed_fd.get();
150-
151-
return fromFileDescriptor(file_descriptor_uri, fd, alignment);
152-
}
153-
154-
Result<FileDataLoader> FileDataLoader::from(
155-
const char* file_name,
156-
size_t alignment) {
157-
ET_CHECK_OR_RETURN_ERROR(
158-
is_power_of_2(alignment),
159-
InvalidArgument,
160-
"Alignment %zu is not a power of 2",
161-
alignment);
162-
163-
// Use open() instead of fopen() to avoid the layer of buffering that
164-
// fopen() does. We will be reading large portions of the file in one shot,
165-
// so buffering does not help.
166-
int fd = ::open(file_name, O_RDONLY);
167-
if (fd < 0) {
168-
ET_LOG(
169-
Error, "Failed to open %s: %s (%d)", file_name, strerror(errno), errno);
170-
return Error::AccessFailed;
171-
}
172-
173-
return fromFileDescriptor(file_name, fd, alignment);
174-
}
175-
176122
namespace {
177123
/**
178124
* FreeableBuffer::FreeFn-compatible callback.

extension/data_loader/file_data_loader.h

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,6 @@ namespace extension {
2626
*/
2727
class FileDataLoader final : public executorch::runtime::DataLoader {
2828
public:
29-
/**
30-
* Creates a new FileDataLoader that wraps the named file descriptor, and the
31-
* ownership of the file descriptor is passed. This helper is used when ET is
32-
* running in a process that does not have access to the filesystem, and the
33-
* caller is able to open the file and pass the file descriptor.
34-
*
35-
* @param[in] file_descriptor_uri File descriptor with the prefix "fd:///",
36-
* followed by the file descriptor number.
37-
* @param[in] alignment Alignment in bytes of pointers returned by this
38-
* instance. Must be a power of two.
39-
*
40-
* @returns A new FileDataLoader on success.
41-
* @retval Error::InvalidArgument `alignment` is not a power of two.
42-
* @retval Error::AccessFailed `file_name` could not be opened, or its size
43-
* could not be found.
44-
* @retval Error::MemoryAllocationFailed Internal memory allocation failure.
45-
*/
46-
static executorch::runtime::Result<FileDataLoader> fromFileDescriptorUri(
47-
const char* file_descriptor_uri,
48-
size_t alignment = alignof(std::max_align_t));
49-
5029
/**
5130
* Creates a new FileDataLoader that wraps the named file.
5231
*
@@ -100,11 +79,6 @@ class FileDataLoader final : public executorch::runtime::DataLoader {
10079
void* buffer) const override;
10180

10281
private:
103-
static executorch::runtime::Result<FileDataLoader> fromFileDescriptor(
104-
const char* file_name,
105-
const int fd,
106-
size_t alignment = alignof(std::max_align_t));
107-
10882
FileDataLoader(
10983
int fd,
11084
size_t file_size,

0 commit comments

Comments
 (0)