Skip to content

Commit 132d5f1

Browse files
authored
Merge branch 'main' into jz/fix-preq-enums
2 parents 4ec59f4 + 124758e commit 132d5f1

File tree

8 files changed

+330
-27
lines changed

8 files changed

+330
-27
lines changed

.ci/scripts/benchmark_tooling/README.md

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,16 @@ python3 .ci/scripts/benchmark_tooling/analyze_benchmark_stability.py \
7777

7878
##### Filtering Options:
7979

80-
- `--device-pools`: Filter by private device pool names (e.g., "samsung-galaxy-s22-5g", "samsung-galaxy-s22plus-5g")
80+
- `--device-pools`: Filter by device pool names (e.g., "apple_iphone_15_private", "samsung_s22_private")
8181
- `--backends`: Filter by specific backend names (e.g.,"xnnpack_q8")
82-
- `--models`: Filter by specific model names (e.g., "mv3", "meta-llama-llama-3.2-1b-instruct-qlora-int4-eo8")
82+
- `--models`: Filter by specific model names (e.g., "mv3", "meta-llama/Llama-3.2-1B-Instruct-SpinQuant_INT4_EO8")
8383

8484
#### Example Usage
8585

8686
Filter by multiple private device pools and models:
8787
```bash
8888
# This fetches all private table data for models 'llama-3.2-1B' and 'mv3'
89-
python3 get_benchmark_analysis_data.py \
89+
python3 .ci/scripts/benchmark_tooling/get_benchmark_analysis_data.py \
9090
--startTime "2025-06-01T00:00:00" \
9191
--endTime "2025-06-11T00:00:00" \
9292
--device-pools 'apple_iphone_15_private' 'samsung_s22_private' \
@@ -97,7 +97,7 @@ Filter by specific device pool and models:
9797
```bash
9898
# This fetches all private iPhone table data for models 'llama-3.2-1B' and 'mv3',
9999
# and associated public iPhone data
100-
python3 get_benchmark_analysis_data.py \
100+
python3 .ci/scripts/benchmark_tooling/get_benchmark_analysis_data.py \
101101
--startTime "2025-06-01T00:00:00" \
102102
--endTime "2025-06-11T00:00:00" \
103103
--device-pools 'apple_iphone_15_private' \
@@ -140,22 +140,6 @@ fetcher.run(
140140
end_time="2025-06-17T18:00:00"
141141
)
142142

143-
# Get results in different formats
144-
# As DataFrames
145-
df_results = fetcher.to_df()
146-
147-
# Export to Excel
148-
fetcher.to_excel(output_dir="./results")
149-
150-
# Export to CSV
151-
fetcher.to_csv(output_dir="./results")
152-
153-
# Export to JSON
154-
json_path = fetcher.to_json(output_dir="./results")
155-
156-
# Get raw dictionary results
157-
dict_results = fetcher.to_dict()
158-
159143
# Use the output_data method for flexible output
160144
results = fetcher.output_data(output_type="excel", output_dir="./results")
161145
```

examples/models/llama/config/llm_config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,9 +227,9 @@ class ExportConfig:
227227
export_only: bool = False
228228

229229
def __post_init__(self):
230-
if self.max_context_length > self.max_seq_length:
230+
if self.max_context_length < self.max_seq_length:
231231
raise ValueError(
232-
f"max_context_length of {self.max_context_length} cannot be greater than max_seq_length of {self.max_seq_length}"
232+
f"max_context_length of {self.max_context_length} cannot be shorter than max_seq_length of {self.max_seq_length}"
233233
)
234234

235235

extension/data_loader/mmap_data_loader.cpp

Lines changed: 80 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,10 @@ void MunmapSegment(void* context, void* data, size_t size) {
150150
}
151151
} // namespace
152152

153-
Result<FreeableBuffer> MmapDataLoader::load(
154-
size_t offset,
155-
size_t size,
156-
ET_UNUSED const DataLoader::SegmentInfo& segment_info) const {
153+
/**
154+
* Validates that file read range is within bounds.
155+
*/
156+
Error MmapDataLoader::validate_input(size_t offset, size_t size) const {
157157
ET_CHECK_OR_RETURN_ERROR(
158158
// Probably had its value moved to another instance.
159159
fd_ >= 0,
@@ -173,6 +173,18 @@ Result<FreeableBuffer> MmapDataLoader::load(
173173
InvalidArgument,
174174
"Offset %zu too large for off_t",
175175
offset);
176+
return Error::Ok;
177+
}
178+
179+
Result<FreeableBuffer> MmapDataLoader::load(
180+
size_t offset,
181+
size_t size,
182+
ET_UNUSED const DataLoader::SegmentInfo& segment_info) const {
183+
// Ensure read range is valid.
184+
auto validation_err = validate_input(offset, size);
185+
if (validation_err != Error::Ok) {
186+
return validation_err;
187+
}
176188

177189
// mmap() will fail if the size is zero.
178190
if (size == 0) {
@@ -267,5 +279,69 @@ Result<size_t> MmapDataLoader::size() const {
267279
return file_size_;
268280
}
269281

282+
Error MmapDataLoader::load_into(
283+
size_t offset,
284+
size_t size,
285+
ET_UNUSED const SegmentInfo& segment_info,
286+
void* buffer) const {
287+
ET_CHECK_OR_RETURN_ERROR(
288+
buffer != nullptr, InvalidArgument, "Buffer is null");
289+
290+
// Ensure read range is valid.
291+
auto err = validate_input(offset, size);
292+
if (err != Error::Ok) {
293+
return err;
294+
}
295+
296+
// Nothing to copy.
297+
if (size == 0) {
298+
return Error::Ok;
299+
}
300+
301+
// Find the range of pages that covers the requested region.
302+
Range range =
303+
get_overlapping_pages(static_cast<uintptr_t>(offset), size, page_size_);
304+
305+
size_t map_size = range.size;
306+
if (range.start + map_size > file_size_) {
307+
// Clamp to the end of the file.
308+
//
309+
// The Windows implementation of mmap uses CreateFileMapping which returns
310+
// error STATUS_SECTION_TOO_BIG (0xc0000040) if we try to map past the end
311+
// of the last page of a file mapped in as read-only.
312+
map_size = file_size_ - range.start;
313+
}
314+
315+
// Map the pages read-only. MAP_PRIVATE vs. MAP_SHARED doesn't matter since
316+
// the data is read-only, but use PRIVATE just to further avoid accidentally
317+
// modifying the file.
318+
void* pages = ::mmap(
319+
nullptr,
320+
map_size,
321+
PROT_READ,
322+
MAP_PRIVATE,
323+
fd_,
324+
static_cast<off_t>(range.start));
325+
ET_CHECK_OR_RETURN_ERROR(
326+
pages != MAP_FAILED,
327+
AccessFailed,
328+
"Failed to map %s: mmap(..., size=%zd, ..., fd=%d, offset=0x%zx)",
329+
file_name_,
330+
range.size,
331+
fd_,
332+
range.start);
333+
334+
// Offset into mapped region.
335+
const size_t map_delta = offset - range.start;
336+
337+
// Copy data into caller's buffer.
338+
std::memcpy(buffer, static_cast<uint8_t*>(pages) + map_delta, size);
339+
340+
// Unmap mapped region.
341+
::munmap(pages, map_size);
342+
343+
return Error::Ok;
344+
}
345+
270346
} // namespace extension
271347
} // namespace executorch

extension/data_loader/mmap_data_loader.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,13 @@ class MmapDataLoader final : public executorch::runtime::DataLoader {
9595

9696
ET_NODISCARD executorch::runtime::Result<size_t> size() const override;
9797

98+
ET_NODISCARD
99+
executorch::runtime::Error load_into(
100+
size_t offset,
101+
size_t size,
102+
ET_UNUSED const SegmentInfo& segment_info,
103+
void* buffer) const override;
104+
98105
private:
99106
MmapDataLoader(
100107
int fd,
@@ -113,6 +120,10 @@ class MmapDataLoader final : public executorch::runtime::DataLoader {
113120
MmapDataLoader& operator=(const MmapDataLoader&) = delete;
114121
MmapDataLoader& operator=(MmapDataLoader&&) = delete;
115122

123+
ET_NODISCARD executorch::runtime::Error validate_input(
124+
size_t offset,
125+
size_t size) const;
126+
116127
const char* const file_name_; // String data is owned by the instance.
117128
const size_t file_size_;
118129
const size_t page_size_;

extension/data_loader/test/mmap_data_loader_test.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,56 @@ TEST_F(MmapDataLoaderTest, DEPRECATEDFrom) {
376376
ASSERT_EQ(total_size.error(), Error::Ok);
377377
EXPECT_EQ(*total_size, contents_size);
378378
}
379+
380+
// Tests that load_into copies bytes correctly.
381+
TEST_F(MmapDataLoaderTest, LoadIntoCopiesCorrectly) {
382+
// Create a test string.
383+
const char* test_text = "FILE_CONTENTS";
384+
const size_t text_size = std::strlen(test_text);
385+
TempFile tf(test_text);
386+
387+
// Wrap it in a loader.
388+
Result<MmapDataLoader> mdl = MmapDataLoader::from(tf.path().c_str());
389+
ASSERT_EQ(mdl.error(), Error::Ok);
390+
391+
// Destination buffer.
392+
std::vector<uint8_t> dst(text_size);
393+
394+
// Call load_into()
395+
Error err = mdl->load_into(
396+
/*offset=*/0,
397+
/*size=*/text_size,
398+
DataLoader::SegmentInfo(DataLoader::SegmentInfo::Type::Program),
399+
dst.data());
400+
ASSERT_EQ(err, Error::Ok);
401+
402+
// Verify memory copied correctly.
403+
EXPECT_EQ(0, std::memcmp(dst.data(), test_text, text_size));
404+
}
405+
406+
// Tests that load_into copies offset slice correctly.
407+
TEST_F(MmapDataLoaderTest, LoadIntoCopiesOffsetCorrectly) {
408+
// Create a test string.
409+
const char* contents = "ABCDEFGH";
410+
TempFile tf(contents);
411+
412+
// Wrap it in a loader.
413+
Result<MmapDataLoader> mdl = MmapDataLoader::from(tf.path().c_str());
414+
ASSERT_EQ(mdl.error(), Error::Ok);
415+
416+
// Copying 3 bytes starting at offset 2 = "CDE"
417+
const size_t offset = 2;
418+
const size_t size = 3;
419+
uint8_t dst[size];
420+
421+
// Call load_into()
422+
Error err = mdl->load_into(
423+
offset,
424+
size,
425+
DataLoader::SegmentInfo(DataLoader::SegmentInfo::Type::Program),
426+
dst);
427+
ASSERT_EQ(err, Error::Ok);
428+
429+
// Verify memory copied correctly.
430+
EXPECT_EQ(0, std::memcmp(dst, contents + offset, size));
431+
}

runtime/backend/interface.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,5 +66,42 @@ Result<const char*> get_backend_name(size_t index) {
6666
return registered_backends[index].name;
6767
}
6868

69+
Error set_option(
70+
const char* backend_name,
71+
const executorch::runtime::Span<executorch::runtime::BackendOption>
72+
backend_options) {
73+
auto backend_class = get_backend_class(backend_name);
74+
if (!backend_class) {
75+
return Error::NotFound;
76+
}
77+
78+
BackendOptionContext backend_option_context;
79+
Error result =
80+
backend_class->set_option(backend_option_context, backend_options);
81+
if (result != Error::Ok) {
82+
return result;
83+
}
84+
return Error::Ok;
85+
}
86+
87+
Error get_option(
88+
const char* backend_name,
89+
executorch::runtime::Span<executorch::runtime::BackendOption>
90+
backend_options) {
91+
auto backend_class = get_backend_class(backend_name);
92+
if (!backend_class) {
93+
return Error::NotFound;
94+
}
95+
BackendOptionContext backend_option_context;
96+
executorch::runtime::Span<BackendOption> backend_options_ref(
97+
backend_options.data(), backend_options.size());
98+
auto result =
99+
backend_class->get_option(backend_option_context, backend_options_ref);
100+
if (result != Error::Ok) {
101+
return result;
102+
}
103+
return Error::Ok;
104+
}
105+
69106
} // namespace ET_RUNTIME_NAMESPACE
70107
} // namespace executorch

runtime/backend/interface.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,34 @@ size_t get_num_registered_backends();
183183
*/
184184
Result<const char*> get_backend_name(size_t index);
185185

186+
/**
187+
* Sets backend options for a specific backend.
188+
*
189+
* @param backend_name The name of the backend to set options for
190+
* @param backend_options The backend option list containing the options
191+
* to set
192+
* @return Error::Ok on success, Error::NotFound if backend is not found, or
193+
* other error codes on failure
194+
*/
195+
Error set_option(
196+
const char* backend_name,
197+
const executorch::runtime::Span<executorch::runtime::BackendOption>
198+
backend_options);
199+
200+
/**
201+
* Retrieves backend options for a specific backend.
202+
*
203+
* @param backend_name The name of the backend to get options from
204+
* @param backend_options The backend option objects that will be filled with
205+
* the populated values from the backend
206+
* @return Error::Ok on success, Error::NotFound if backend is not found, or
207+
* other error codes on failure
208+
*/
209+
Error get_option(
210+
const char* backend_name,
211+
executorch::runtime::Span<executorch::runtime::BackendOption>
212+
backend_options);
213+
186214
} // namespace ET_RUNTIME_NAMESPACE
187215
} // namespace executorch
188216

0 commit comments

Comments
 (0)