From 7069ec9b3a05c35102d3b848c1514e372acda378 Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Fri, 2 Aug 2024 14:55:45 -0700 Subject: [PATCH 01/11] enable large initializer offset align for save external data in ORT --- include/onnxruntime/core/graph/graph.h | 14 +++++++- onnxruntime/core/graph/graph.cc | 21 ++++++++++- onnxruntime/core/graph/model.cc | 36 ++++++++++++++----- onnxruntime/core/graph/model.h | 17 +++++++-- onnxruntime/core/session/inference_session.cc | 3 +- .../save_model_with_external_initializers.cc | 24 +++++++++++-- 6 files changed, 99 insertions(+), 16 deletions(-) diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index c51f38553c3b4..ddbc7cc33be75 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1144,11 +1144,23 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi @param model_file_path path of the model file. @param initializer_size_threshold initializers larger or equal to this threshold (in bytes) are saved in the external file. Initializer smaller than this threshold are included in the onnx file. + @align_offset offset will always be page aligned and alloction granularity aligned for mmap support. + This is done by padding previous tensor data with zeros keeping same length. + Tensor data will be aligned if > align_threshold + @align_threshold alignment threshold for size of data. + Having a low threshold will waste file space for small initializers. + Only when tensor's data is > the page_align_threshold it will be force aligned. + Default to 1MB. + @allocation_granularity the allocation Granularity for mmap() support. + Typically 64KB for Windows & 4KB for other OSes. Default to 64KB. @returns GraphProto serialization of the graph. */ ONNX_NAMESPACE::GraphProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, const std::filesystem::path& model_file_path, - size_t initializer_size_threshold) const; + size_t initializer_size_threshold, + bool align_offset = FALSE, + size_t align_threshold = 1048576, + size_t allocation_granularity = 65536) const; /** Gets the ISchemaRegistry instances being used with this Graph. */ IOnnxRuntimeOpSchemaCollectionPtr GetSchemaRegistry() const; diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index e950d68947b91..f3b7bad572d85 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -4021,7 +4021,10 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProto() const { ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, const std::filesystem::path& model_file_path, - size_t initializer_size_threshold) const { + size_t initializer_size_threshold, + bool align_offset, + size_t align_threshold, + size_t allocation_granularity) const { GraphProto result; ToGraphProtoInternal(result); ORT_ENFORCE(external_file_path.is_relative()); @@ -4063,6 +4066,22 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std external_stream << raw_data[index]; } + // update external_offset for alignment + if (align_offset && tensor_bytes_size > align_threshold) { + // Align to the larger of the page size or the allocation granularity + size_t alignment_factor = std::max(static_cast(4096), allocation_granularity); + // Align to the next page or alloc granularity boundary + size_t new_external_offset = static_cast( + std::floor((external_offset + alignment_factor - 1) / alignment_factor)) * alignment_factor; + + // padding tensor with zeros for alignment + for (size_t index = external_offset; index != new_external_offset; ++index) { + external_stream << '0'; + } + + external_offset = new_external_offset; + } + output_proto->set_data_location(ONNX_NAMESPACE::TensorProto_DataLocation::TensorProto_DataLocation_EXTERNAL); ONNX_NAMESPACE::StringStringEntryProto* location = output_proto->add_external_data(); location->set_key("location"); diff --git a/onnxruntime/core/graph/model.cc b/onnxruntime/core/graph/model.cc index ee4d9f9154971..be086c167e611 100644 --- a/onnxruntime/core/graph/model.cc +++ b/onnxruntime/core/graph/model.cc @@ -383,12 +383,18 @@ ModelProto Model::ToProto() const { ModelProto Model::ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, const std::filesystem::path& file_path, - size_t initializer_size_threshold) const { + size_t initializer_size_threshold, + bool align_offset, + size_t align_threshold, + size_t allocation_granularity) const { ModelProto result(model_proto_); const auto& graph = *graph_; *(result.mutable_graph()) = graph.ToGraphProtoWithExternalInitializers(external_file_name, file_path, - initializer_size_threshold); + initializer_size_threshold, + align_offset, + align_threshold, + allocation_granularity); return result; } @@ -605,14 +611,19 @@ template static Status SaveModelWithExternalInitializers(Model& model, const T& file_path, const std::filesystem::path& external_file_name, - size_t initializer_size_threshold) { + size_t initializer_size_threshold, + bool align_offset = FALSE, + size_t align_threshold = 1048576, + size_t allocation_granularity = 65536) { int fd = 0; Status status = Env::Default().FileOpenWr(file_path, fd); ORT_RETURN_IF_ERROR(status); ORT_TRY { status = Model::SaveWithExternalInitializers(model, fd, file_path, external_file_name, - initializer_size_threshold); + initializer_size_threshold, + align_offset, align_threshold, + allocation_granularity); } ORT_CATCH(const std::exception& ex) { ORT_HANDLE_EXCEPTION([&]() { @@ -642,8 +653,12 @@ Status Model::Load(const PathString& file_path, std::shared_ptr& p_model, Status Model::SaveWithExternalInitializers(Model& model, const std::filesystem::path& file_path, const std::filesystem::path& external_file_name, - size_t initializer_size_threshold) { - return SaveModelWithExternalInitializers(model, file_path, external_file_name, initializer_size_threshold); + size_t initializer_size_threshold, + bool align_offset, + size_t align_threshold, + size_t allocation_granularity) { + return SaveModelWithExternalInitializers(model, file_path, external_file_name, initializer_size_threshold, + align_offset, align_threshold, allocation_granularity); } Status Model::LoadFromBytes(int count, void* p_bytes, /*out*/ ONNX_NAMESPACE::ModelProto& model_proto) { @@ -759,7 +774,10 @@ Status Model::SaveWithExternalInitializers(Model& model, int fd, const std::filesystem::path& file_path, const std::filesystem::path& external_file_name, - size_t initializer_size_threshold) { + size_t initializer_size_threshold, + bool align_offset, + size_t align_threshold, + size_t allocation_granularity) { if (fd < 0) { return Status(ONNXRUNTIME, INVALID_ARGUMENT, " is less than 0."); } @@ -767,7 +785,9 @@ Status Model::SaveWithExternalInitializers(Model& model, ORT_RETURN_IF_ERROR(model.MainGraph().Resolve()); auto model_proto = model.ToGraphProtoWithExternalInitializers(external_file_name, file_path, - initializer_size_threshold); + initializer_size_threshold, + align_offset, align_threshold, + allocation_granularity); google::protobuf::io::FileOutputStream output(fd); const bool result = model_proto.SerializeToZeroCopyStream(&output) && output.Flush(); if (result) { diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index 728af727ac83b..49ab0882147f5 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -187,25 +187,36 @@ class Model { // Get model's serialization proto data. // Save initializer larger than the given threshold (in bytes) into an external binary file // with the given name. This function is useful to avoid hitting the size limit of protobuf files. + // initializer offset could be page aligned and allocation granularity aligned for mmap support. ONNX_NAMESPACE::ModelProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, const std::filesystem::path& file_path, - size_t initializer_size_threshold) const; + size_t initializer_size_threshold, + bool align_offset = FALSE, + size_t align_threshold = 1048576, + size_t allocation_granularity = 65536) const; static common::Status Save(Model& model, const PathString& file_path); static common::Status Save(Model& model, int fd); // Save the model to file using an external file for initializers larger than the given threshold (in bytes). + // Initializer offset could be page aligned and allocation granularity aligned for mmap support. static common::Status SaveWithExternalInitializers(Model& model, const std::filesystem::path& file_path, const std::filesystem::path& external_file_path, - size_t initializer_size_threshold); + size_t initializer_size_threshold, + bool align_offset = FALSE, + size_t align_threshold = 1048576, + size_t allocation_granularity = 65536); static common::Status SaveWithExternalInitializers(Model& model, int fd, const std::filesystem::path& file_path, const std::filesystem::path& external_file_path, - size_t initializer_size_threshold); + size_t initializer_size_threshold, + bool align_offset = FALSE, + size_t align_threshold = 1048576, + size_t allocation_granularity = 65536); static common::Status Load(std::istream& model_istream, ONNX_NAMESPACE::ModelProto* p_model_proto); diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index 5ad2f08467792..e7af1b09da96c 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -2055,7 +2055,8 @@ common::Status InferenceSession::Initialize() { ORT_RETURN_IF_ERROR_SESSIONID_(Model::SaveWithExternalInitializers(*model_, session_options_.optimized_model_filepath, optimized_model_external_initializers_file_name, - optimized_model_external_initializers_min_size_in_bytes)); + optimized_model_external_initializers_min_size_in_bytes, + TRUE)); } } } diff --git a/onnxruntime/test/framework/save_model_with_external_initializers.cc b/onnxruntime/test/framework/save_model_with_external_initializers.cc index 447b0edef879b..3ea66e55dce84 100644 --- a/onnxruntime/test/framework/save_model_with_external_initializers.cc +++ b/onnxruntime/test/framework/save_model_with_external_initializers.cc @@ -23,13 +23,17 @@ Status LoadSaveAndCompareModel(const std::filesystem::path& input_onnx, const std::filesystem::path& input_external_init_file, const std::filesystem::path& output_onnx, const std::filesystem::path& output_external_init_file, - size_t initializer_size_threshold) { + size_t initializer_size_threshold, + bool align_offset = false, + size_t align_threshold = 1, + size_t allocation_granularity = 4096) { auto logger = DefaultLoggingManager().CreateLogger("LoadSaveAndCompareModel"); std::shared_ptr model; ORT_RETURN_IF_ERROR(Model::Load(input_onnx, model, nullptr, *logger)); std::filesystem::remove(output_onnx); std::filesystem::remove(output_external_init_file); - ORT_RETURN_IF_ERROR(Model::SaveWithExternalInitializers(*model, output_onnx, output_external_init_file, initializer_size_threshold)); + ORT_RETURN_IF_ERROR(Model::SaveWithExternalInitializers(*model, output_onnx, output_external_init_file, initializer_size_threshold, + align_offset, align_threshold, allocation_granularity)); std::shared_ptr model_from_external; ORT_RETURN_IF_ERROR(Model::Load(output_onnx.native(), model_from_external, nullptr, *logger)); @@ -75,6 +79,17 @@ Status LoadSaveAndCompareModel(const std::filesystem::path& input_onnx, ORT_RETURN_IF_NOT(tensor_proto_size == from_external_tensor_proto_size, "size mismatch"); ORT_RETURN_IF_NOT(memcmp(tensor_proto_data.data(), from_external_tensor_proto_data.data(), tensor_proto_size) == 0, "data mismatch"); + + if (align_offset) { + for (const StringStringEntryProto& entry : from_external_tensor_proto->external_data()) { + if (entry.has_key() && entry.has_value() && entry.key() == "offset") { + size_t tensor_offset; + std::stringstream stream(entry.value()); + stream >> tensor_offset; + ORT_RETURN_IF_NOT(tensor_offset % allocation_granularity == 0, "tensor offset not align"); + } + } + } } // Cleanup. ORT_RETURN_IF_NOT(std::filesystem::remove(output_onnx), "delete file failed"); @@ -92,5 +107,10 @@ TEST(SaveWithExternalInitializers, ModelWithOriginalExternalData) { ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0)); } +// Original model has external initializers, align offset +TEST(SaveWithExternalInitializers, ModelWithOriginalExternalDataAlignOffset) { + ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0, true)); +} + } // namespace test } // namespace onnxruntime From 989d57e9e76699443ca637c27ef387ad14738487 Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Fri, 2 Aug 2024 15:10:09 -0700 Subject: [PATCH 02/11] fix true false --- include/onnxruntime/core/graph/graph.h | 2 +- onnxruntime/core/graph/model.cc | 2 +- onnxruntime/core/graph/model.h | 6 +++--- onnxruntime/core/session/inference_session.cc | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index ddbc7cc33be75..3d2f4894624eb 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1158,7 +1158,7 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi ONNX_NAMESPACE::GraphProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, const std::filesystem::path& model_file_path, size_t initializer_size_threshold, - bool align_offset = FALSE, + bool align_offset = false, size_t align_threshold = 1048576, size_t allocation_granularity = 65536) const; diff --git a/onnxruntime/core/graph/model.cc b/onnxruntime/core/graph/model.cc index be086c167e611..24e6d579ba975 100644 --- a/onnxruntime/core/graph/model.cc +++ b/onnxruntime/core/graph/model.cc @@ -612,7 +612,7 @@ static Status SaveModelWithExternalInitializers(Model& model, const T& file_path, const std::filesystem::path& external_file_name, size_t initializer_size_threshold, - bool align_offset = FALSE, + bool align_offset = false, size_t align_threshold = 1048576, size_t allocation_granularity = 65536) { int fd = 0; diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index 49ab0882147f5..b3da1e4666581 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -191,7 +191,7 @@ class Model { ONNX_NAMESPACE::ModelProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, const std::filesystem::path& file_path, size_t initializer_size_threshold, - bool align_offset = FALSE, + bool align_offset = false, size_t align_threshold = 1048576, size_t allocation_granularity = 65536) const; @@ -205,7 +205,7 @@ class Model { const std::filesystem::path& file_path, const std::filesystem::path& external_file_path, size_t initializer_size_threshold, - bool align_offset = FALSE, + bool align_offset = false, size_t align_threshold = 1048576, size_t allocation_granularity = 65536); @@ -214,7 +214,7 @@ class Model { const std::filesystem::path& file_path, const std::filesystem::path& external_file_path, size_t initializer_size_threshold, - bool align_offset = FALSE, + bool align_offset = false, size_t align_threshold = 1048576, size_t allocation_granularity = 65536); diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index e7af1b09da96c..a275c7b6ea1c8 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -2056,7 +2056,7 @@ common::Status InferenceSession::Initialize() { session_options_.optimized_model_filepath, optimized_model_external_initializers_file_name, optimized_model_external_initializers_min_size_in_bytes, - TRUE)); + true)); } } } From 6f7b950edbf1a795aba82302b5906233a0346885 Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Fri, 2 Aug 2024 15:49:30 -0700 Subject: [PATCH 03/11] lint format fix --- include/onnxruntime/core/graph/graph.h | 6 +++--- onnxruntime/core/graph/graph.cc | 5 +++-- onnxruntime/core/graph/model.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index 3d2f4894624eb..890b05afd171d 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1144,11 +1144,11 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi @param model_file_path path of the model file. @param initializer_size_threshold initializers larger or equal to this threshold (in bytes) are saved in the external file. Initializer smaller than this threshold are included in the onnx file. - @align_offset offset will always be page aligned and alloction granularity aligned for mmap support. - This is done by padding previous tensor data with zeros keeping same length. + @align_offset offset will always be page aligned and alloction granularity aligned for mmap support. + This is done by padding previous tensor data with zeros keeping same length. Tensor data will be aligned if > align_threshold @align_threshold alignment threshold for size of data. - Having a low threshold will waste file space for small initializers. + Having a low threshold will waste file space for small initializers. Only when tensor's data is > the page_align_threshold it will be force aligned. Default to 1MB. @allocation_granularity the allocation Granularity for mmap() support. diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index f3b7bad572d85..9c0b492948d1c 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -4034,7 +4034,7 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std std::ofstream external_stream(modified_external_file_path, std::ofstream::out | std::ofstream::binary); ORT_ENFORCE(external_stream.is_open()); - int64_t external_offset = 0; + size_t external_offset = 0; // Add the initializers to the result graph. const auto& model_path = ModelPath(); @@ -4072,7 +4072,8 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std size_t alignment_factor = std::max(static_cast(4096), allocation_granularity); // Align to the next page or alloc granularity boundary size_t new_external_offset = static_cast( - std::floor((external_offset + alignment_factor - 1) / alignment_factor)) * alignment_factor; + std::floor((external_offset + alignment_factor - 1) / alignment_factor)) * + alignment_factor; // padding tensor with zeros for alignment for (size_t index = external_offset; index != new_external_offset; ++index) { diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index b3da1e4666581..8162f0ff1b705 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -187,7 +187,7 @@ class Model { // Get model's serialization proto data. // Save initializer larger than the given threshold (in bytes) into an external binary file // with the given name. This function is useful to avoid hitting the size limit of protobuf files. - // initializer offset could be page aligned and allocation granularity aligned for mmap support. + // initializer offset could be page aligned and allocation granularity aligned for mmap support. ONNX_NAMESPACE::ModelProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, const std::filesystem::path& file_path, size_t initializer_size_threshold, From 6d847dafaa5800db25a4d90ec3cfe1c79bb5e38e Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Mon, 5 Aug 2024 17:52:30 -0700 Subject: [PATCH 04/11] take comments --- include/onnxruntime/core/graph/graph.h | 36 ++++++++++++------- onnxruntime/core/graph/graph.cc | 8 ++--- onnxruntime/core/graph/model.cc | 28 +++++---------- onnxruntime/core/graph/model.h | 36 ++++++++++++++----- onnxruntime/core/session/inference_session.cc | 4 ++- .../save_model_with_external_initializers.cc | 20 ++++++----- 6 files changed, 76 insertions(+), 56 deletions(-) diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index 890b05afd171d..33b36d2cb7ce8 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1139,28 +1139,40 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi const ONNX_NAMESPACE::GraphProto& ToGraphProto(); ONNX_NAMESPACE::GraphProto ToGraphProto() const; + // Options to align external initializer offset. + struct OffsetAlignmentInfo { + // Offset will always be page aligned and allocation granularity aligned for mmap support. + // This is done by padding previous tensor data with zeros keeping same length. + bool align_offset = false; + // Alignment threshold for size of data. + // Having a low threshold will waste file space for small initializers. + // Only when tensor's data is > the page_align_threshold it will be force aligned. + // Default to 1MB. + size_t align_threshold = 1048576; + // The allocation Granularity for mmap() support. + // Typically 64KB for Windows & 4KB for other OSes. Default to 64KB. + size_t allocation_granularity = 65536; + }; + /** Gets the GraphProto representation of this Graph @param external_file_path File path of the binary file to use for initializers. @param model_file_path path of the model file. @param initializer_size_threshold initializers larger or equal to this threshold (in bytes) are saved in the external file. Initializer smaller than this threshold are included in the onnx file. - @align_offset offset will always be page aligned and alloction granularity aligned for mmap support. - This is done by padding previous tensor data with zeros keeping same length. - Tensor data will be aligned if > align_threshold - @align_threshold alignment threshold for size of data. - Having a low threshold will waste file space for small initializers. - Only when tensor's data is > the page_align_threshold it will be force aligned. - Default to 1MB. - @allocation_granularity the allocation Granularity for mmap() support. - Typically 64KB for Windows & 4KB for other OSes. Default to 64KB. + @param align_info offset alignment info. @returns GraphProto serialization of the graph. */ ONNX_NAMESPACE::GraphProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, const std::filesystem::path& model_file_path, size_t initializer_size_threshold, - bool align_offset = false, - size_t align_threshold = 1048576, - size_t allocation_granularity = 65536) const; + const OffsetAlignmentInfo& align_info) const; + + ONNX_NAMESPACE::GraphProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, + const std::filesystem::path& model_file_path, + size_t initializer_size_threshold) const { + OffsetAlignmentInfo default_options; + return ToGraphProtoWithExternalInitializers(external_file_path, model_file_path, initializer_size_threshold, default_options); + } /** Gets the ISchemaRegistry instances being used with this Graph. */ IOnnxRuntimeOpSchemaCollectionPtr GetSchemaRegistry() const; diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index 9c0b492948d1c..30f654b9efa69 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -4022,9 +4022,7 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProto() const { ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_path, const std::filesystem::path& model_file_path, size_t initializer_size_threshold, - bool align_offset, - size_t align_threshold, - size_t allocation_granularity) const { + const OffsetAlignmentInfo& align_info) const { GraphProto result; ToGraphProtoInternal(result); ORT_ENFORCE(external_file_path.is_relative()); @@ -4067,9 +4065,9 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std } // update external_offset for alignment - if (align_offset && tensor_bytes_size > align_threshold) { + if (align_info.align_offset && tensor_bytes_size > align_info.align_threshold) { // Align to the larger of the page size or the allocation granularity - size_t alignment_factor = std::max(static_cast(4096), allocation_granularity); + size_t alignment_factor = std::max(static_cast(4096), align_info.allocation_granularity); // Align to the next page or alloc granularity boundary size_t new_external_offset = static_cast( std::floor((external_offset + alignment_factor - 1) / alignment_factor)) * diff --git a/onnxruntime/core/graph/model.cc b/onnxruntime/core/graph/model.cc index 24e6d579ba975..750874a651d6e 100644 --- a/onnxruntime/core/graph/model.cc +++ b/onnxruntime/core/graph/model.cc @@ -384,17 +384,13 @@ ModelProto Model::ToProto() const { ModelProto Model::ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, const std::filesystem::path& file_path, size_t initializer_size_threshold, - bool align_offset, - size_t align_threshold, - size_t allocation_granularity) const { + const Graph::OffsetAlignmentInfo& align_info) const { ModelProto result(model_proto_); const auto& graph = *graph_; *(result.mutable_graph()) = graph.ToGraphProtoWithExternalInitializers(external_file_name, file_path, initializer_size_threshold, - align_offset, - align_threshold, - allocation_granularity); + align_info); return result; } @@ -612,9 +608,7 @@ static Status SaveModelWithExternalInitializers(Model& model, const T& file_path, const std::filesystem::path& external_file_name, size_t initializer_size_threshold, - bool align_offset = false, - size_t align_threshold = 1048576, - size_t allocation_granularity = 65536) { + const Graph::OffsetAlignmentInfo& align_info) { int fd = 0; Status status = Env::Default().FileOpenWr(file_path, fd); ORT_RETURN_IF_ERROR(status); @@ -622,8 +616,7 @@ static Status SaveModelWithExternalInitializers(Model& model, ORT_TRY { status = Model::SaveWithExternalInitializers(model, fd, file_path, external_file_name, initializer_size_threshold, - align_offset, align_threshold, - allocation_granularity); + align_info); } ORT_CATCH(const std::exception& ex) { ORT_HANDLE_EXCEPTION([&]() { @@ -654,11 +647,9 @@ Status Model::Load(const PathString& file_path, std::shared_ptr& p_model, Status Model::SaveWithExternalInitializers(Model& model, const std::filesystem::path& file_path, const std::filesystem::path& external_file_name, size_t initializer_size_threshold, - bool align_offset, - size_t align_threshold, - size_t allocation_granularity) { + const Graph::OffsetAlignmentInfo& align_info) { return SaveModelWithExternalInitializers(model, file_path, external_file_name, initializer_size_threshold, - align_offset, align_threshold, allocation_granularity); + align_info); } Status Model::LoadFromBytes(int count, void* p_bytes, /*out*/ ONNX_NAMESPACE::ModelProto& model_proto) { @@ -775,9 +766,7 @@ Status Model::SaveWithExternalInitializers(Model& model, const std::filesystem::path& file_path, const std::filesystem::path& external_file_name, size_t initializer_size_threshold, - bool align_offset, - size_t align_threshold, - size_t allocation_granularity) { + const Graph::OffsetAlignmentInfo& align_info) { if (fd < 0) { return Status(ONNXRUNTIME, INVALID_ARGUMENT, " is less than 0."); } @@ -786,8 +775,7 @@ Status Model::SaveWithExternalInitializers(Model& model, auto model_proto = model.ToGraphProtoWithExternalInitializers(external_file_name, file_path, initializer_size_threshold, - align_offset, align_threshold, - allocation_granularity); + align_info); google::protobuf::io::FileOutputStream output(fd); const bool result = model_proto.SerializeToZeroCopyStream(&output) && output.Flush(); if (result) { diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index 8162f0ff1b705..5fa55eed04fae 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -191,9 +191,14 @@ class Model { ONNX_NAMESPACE::ModelProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, const std::filesystem::path& file_path, size_t initializer_size_threshold, - bool align_offset = false, - size_t align_threshold = 1048576, - size_t allocation_granularity = 65536) const; + const Graph::OffsetAlignmentInfo& align_info) const; + + ONNX_NAMESPACE::ModelProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, + const std::filesystem::path& file_path, + size_t initializer_size_threshold) const { + Graph::OffsetAlignmentInfo default_align_info; + return ToGraphProtoWithExternalInitializers(external_file_name, file_path, initializer_size_threshold, default_align_info); + } static common::Status Save(Model& model, const PathString& file_path); @@ -205,18 +210,31 @@ class Model { const std::filesystem::path& file_path, const std::filesystem::path& external_file_path, size_t initializer_size_threshold, - bool align_offset = false, - size_t align_threshold = 1048576, - size_t allocation_granularity = 65536); + const Graph::OffsetAlignmentInfo& align_info); + + static common::Status SaveWithExternalInitializers(Model& model, + const std::filesystem::path& file_path, + const std::filesystem::path& external_file_path, + size_t initializer_size_threshold) { + Graph::OffsetAlignmentInfo default_align_info; + return SaveWithExternalInitializers(model, file_path, external_file_path, initializer_size_threshold, default_align_info); + } static common::Status SaveWithExternalInitializers(Model& model, int fd, const std::filesystem::path& file_path, const std::filesystem::path& external_file_path, size_t initializer_size_threshold, - bool align_offset = false, - size_t align_threshold = 1048576, - size_t allocation_granularity = 65536); + const Graph::OffsetAlignmentInfo& align_info); + + static common::Status SaveWithExternalInitializers(Model& model, + int fd, + const std::filesystem::path& file_path, + const std::filesystem::path& external_file_path, + size_t initializer_size_threshold) { + Graph::OffsetAlignmentInfo default_align_info; + return SaveWithExternalInitializers(model, fd, file_path, external_file_path, initializer_size_threshold, default_align_info); + } static common::Status Load(std::istream& model_istream, ONNX_NAMESPACE::ModelProto* p_model_proto); diff --git a/onnxruntime/core/session/inference_session.cc b/onnxruntime/core/session/inference_session.cc index a275c7b6ea1c8..d3ebc8628034d 100644 --- a/onnxruntime/core/session/inference_session.cc +++ b/onnxruntime/core/session/inference_session.cc @@ -2052,11 +2052,13 @@ common::Status InferenceSession::Initialize() { const size_t optimized_model_external_initializers_min_size_in_bytes = ParseStringWithClassicLocale(session_options_.config_options.GetConfigOrDefault( kOrtSessionOptionsOptimizedModelExternalInitializersMinSizeInBytes, "1024")); + Graph::OffsetAlignmentInfo align_info; + align_info.align_offset = true; ORT_RETURN_IF_ERROR_SESSIONID_(Model::SaveWithExternalInitializers(*model_, session_options_.optimized_model_filepath, optimized_model_external_initializers_file_name, optimized_model_external_initializers_min_size_in_bytes, - true)); + align_info)); } } } diff --git a/onnxruntime/test/framework/save_model_with_external_initializers.cc b/onnxruntime/test/framework/save_model_with_external_initializers.cc index 3ea66e55dce84..5b7b5153b58ec 100644 --- a/onnxruntime/test/framework/save_model_with_external_initializers.cc +++ b/onnxruntime/test/framework/save_model_with_external_initializers.cc @@ -24,16 +24,14 @@ Status LoadSaveAndCompareModel(const std::filesystem::path& input_onnx, const std::filesystem::path& output_onnx, const std::filesystem::path& output_external_init_file, size_t initializer_size_threshold, - bool align_offset = false, - size_t align_threshold = 1, - size_t allocation_granularity = 4096) { + const Graph::OffsetAlignmentInfo& align_info) { auto logger = DefaultLoggingManager().CreateLogger("LoadSaveAndCompareModel"); std::shared_ptr model; ORT_RETURN_IF_ERROR(Model::Load(input_onnx, model, nullptr, *logger)); std::filesystem::remove(output_onnx); std::filesystem::remove(output_external_init_file); ORT_RETURN_IF_ERROR(Model::SaveWithExternalInitializers(*model, output_onnx, output_external_init_file, initializer_size_threshold, - align_offset, align_threshold, allocation_granularity)); + align_info)); std::shared_ptr model_from_external; ORT_RETURN_IF_ERROR(Model::Load(output_onnx.native(), model_from_external, nullptr, *logger)); @@ -80,13 +78,13 @@ Status LoadSaveAndCompareModel(const std::filesystem::path& input_onnx, ORT_RETURN_IF_NOT(tensor_proto_size == from_external_tensor_proto_size, "size mismatch"); ORT_RETURN_IF_NOT(memcmp(tensor_proto_data.data(), from_external_tensor_proto_data.data(), tensor_proto_size) == 0, "data mismatch"); - if (align_offset) { + if (align_info.align_offset) { for (const StringStringEntryProto& entry : from_external_tensor_proto->external_data()) { if (entry.has_key() && entry.has_value() && entry.key() == "offset") { size_t tensor_offset; std::stringstream stream(entry.value()); stream >> tensor_offset; - ORT_RETURN_IF_NOT(tensor_offset % allocation_granularity == 0, "tensor offset not align"); + ORT_RETURN_IF_NOT(tensor_offset % align_info.allocation_granularity == 0, "tensor offset not align"); } } } @@ -99,17 +97,21 @@ Status LoadSaveAndCompareModel(const std::filesystem::path& input_onnx, // Original model does not have external initializers TEST(SaveWithExternalInitializers, Mnist) { - ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/mnist.onnx"), ORT_TSTR(""), ORT_TSTR("testdata/mnist_with_external_initializers.onnx"), ORT_TSTR("mnist_external_initializers.bin"), 100)); + Graph::OffsetAlignmentInfo align_info; + ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/mnist.onnx"), ORT_TSTR(""), ORT_TSTR("testdata/mnist_with_external_initializers.onnx"), ORT_TSTR("mnist_external_initializers.bin"), 100, align_info)); } // Original model has external initializers TEST(SaveWithExternalInitializers, ModelWithOriginalExternalData) { - ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0)); + Graph::OffsetAlignmentInfo align_info; + ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0, align_info)); } // Original model has external initializers, align offset TEST(SaveWithExternalInitializers, ModelWithOriginalExternalDataAlignOffset) { - ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0, true)); + Graph::OffsetAlignmentInfo align_info; + align_info.align_offset = true; + ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0, align_info)); } } // namespace test From 0aca8f6aaececa4199c2de904b5daba3546e13c7 Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Mon, 5 Aug 2024 21:17:54 -0700 Subject: [PATCH 05/11] lint style --- onnxruntime/core/graph/model.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/onnxruntime/core/graph/model.h b/onnxruntime/core/graph/model.h index 5fa55eed04fae..2cd4f7e1c6c66 100644 --- a/onnxruntime/core/graph/model.h +++ b/onnxruntime/core/graph/model.h @@ -194,8 +194,8 @@ class Model { const Graph::OffsetAlignmentInfo& align_info) const; ONNX_NAMESPACE::ModelProto ToGraphProtoWithExternalInitializers(const std::filesystem::path& external_file_name, - const std::filesystem::path& file_path, - size_t initializer_size_threshold) const { + const std::filesystem::path& file_path, + size_t initializer_size_threshold) const { Graph::OffsetAlignmentInfo default_align_info; return ToGraphProtoWithExternalInitializers(external_file_name, file_path, initializer_size_threshold, default_align_info); } @@ -213,9 +213,9 @@ class Model { const Graph::OffsetAlignmentInfo& align_info); static common::Status SaveWithExternalInitializers(Model& model, - const std::filesystem::path& file_path, - const std::filesystem::path& external_file_path, - size_t initializer_size_threshold) { + const std::filesystem::path& file_path, + const std::filesystem::path& external_file_path, + size_t initializer_size_threshold) { Graph::OffsetAlignmentInfo default_align_info; return SaveWithExternalInitializers(model, file_path, external_file_path, initializer_size_threshold, default_align_info); } @@ -228,10 +228,10 @@ class Model { const Graph::OffsetAlignmentInfo& align_info); static common::Status SaveWithExternalInitializers(Model& model, - int fd, - const std::filesystem::path& file_path, - const std::filesystem::path& external_file_path, - size_t initializer_size_threshold) { + int fd, + const std::filesystem::path& file_path, + const std::filesystem::path& external_file_path, + size_t initializer_size_threshold) { Graph::OffsetAlignmentInfo default_align_info; return SaveWithExternalInitializers(model, fd, file_path, external_file_path, initializer_size_threshold, default_align_info); } From c3ecf4a498e7e91d60dac8abaa58d8aaf8d8bb3e Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Tue, 6 Aug 2024 12:56:18 -0700 Subject: [PATCH 06/11] update test --- .../test/framework/save_model_with_external_initializers.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/onnxruntime/test/framework/save_model_with_external_initializers.cc b/onnxruntime/test/framework/save_model_with_external_initializers.cc index 5b7b5153b58ec..d0bc088175755 100644 --- a/onnxruntime/test/framework/save_model_with_external_initializers.cc +++ b/onnxruntime/test/framework/save_model_with_external_initializers.cc @@ -111,6 +111,7 @@ TEST(SaveWithExternalInitializers, ModelWithOriginalExternalData) { TEST(SaveWithExternalInitializers, ModelWithOriginalExternalDataAlignOffset) { Graph::OffsetAlignmentInfo align_info; align_info.align_offset = true; + align_info.align_threshold = 0; ASSERT_STATUS_OK(LoadSaveAndCompareModel(ORT_TSTR("testdata/model_with_orig_ext_data.onnx"), ORT_TSTR("model_with_orig_ext_data.onnx.data"), ORT_TSTR("testdata/model_with_new_external_initializers.onnx"), ORT_TSTR("model_with_new_external_initializers.bin"), 0, align_info)); } From 390dd8e78a993c5eb610803dcba720ec82301a24 Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Thu, 8 Aug 2024 15:13:24 -0700 Subject: [PATCH 07/11] fix CI error --- include/onnxruntime/core/graph/graph.h | 4 ++-- onnxruntime/core/graph/graph.cc | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index 33b36d2cb7ce8..8d7be5884182a 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1148,10 +1148,10 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi // Having a low threshold will waste file space for small initializers. // Only when tensor's data is > the page_align_threshold it will be force aligned. // Default to 1MB. - size_t align_threshold = 1048576; + int64_t align_threshold = 1048576; // The allocation Granularity for mmap() support. // Typically 64KB for Windows & 4KB for other OSes. Default to 64KB. - size_t allocation_granularity = 65536; + int64_t allocation_granularity = 65536; }; /** Gets the GraphProto representation of this Graph diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index 30f654b9efa69..110cc69ed0bd9 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -4032,7 +4032,7 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std std::ofstream external_stream(modified_external_file_path, std::ofstream::out | std::ofstream::binary); ORT_ENFORCE(external_stream.is_open()); - size_t external_offset = 0; + int64_t external_offset = 0; // Add the initializers to the result graph. const auto& model_path = ModelPath(); @@ -4065,16 +4065,16 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std } // update external_offset for alignment - if (align_info.align_offset && tensor_bytes_size > align_info.align_threshold) { + if (align_info.align_offset && static_cast(tensor_bytes_size) > align_info.align_threshold) { // Align to the larger of the page size or the allocation granularity - size_t alignment_factor = std::max(static_cast(4096), align_info.allocation_granularity); + int64_t alignment_factor = std::max(static_cast(4096), align_info.allocation_granularity); // Align to the next page or alloc granularity boundary - size_t new_external_offset = static_cast( - std::floor((external_offset + alignment_factor - 1) / alignment_factor)) * - alignment_factor; + int64_t new_external_offset = static_cast( + std::floor((external_offset + alignment_factor - 1) / alignment_factor)) * + alignment_factor; // padding tensor with zeros for alignment - for (size_t index = external_offset; index != new_external_offset; ++index) { + for (int64_t index = external_offset; index != new_external_offset; ++index) { external_stream << '0'; } From 3387acd455e871827e9e644a655a62af89f55f62 Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Tue, 20 Aug 2024 19:39:12 -0700 Subject: [PATCH 08/11] fix bug --- onnxruntime/core/graph/graph.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/onnxruntime/core/graph/graph.cc b/onnxruntime/core/graph/graph.cc index 110cc69ed0bd9..7e82edabedbb3 100644 --- a/onnxruntime/core/graph/graph.cc +++ b/onnxruntime/core/graph/graph.cc @@ -4060,11 +4060,11 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std continue; } - for (size_t index = 0; index != tensor_bytes_size; ++index) { - external_stream << raw_data[index]; - } - // update external_offset for alignment + // need to do padding before write actual tensor data as we do offset alignment at the begin of + // large tensors (offset need to be page aligned and alloction granularity aligned) like below: + // \242\2557\256\023.\031&0000000000000000\332)k+\253\246\342\246(&\006!\347\232\374\236\325\026\032+\36XXXX + // |<---small tensor---->|<---padding--->|<------------------large tensor----------------------------->| if (align_info.align_offset && static_cast(tensor_bytes_size) > align_info.align_threshold) { // Align to the larger of the page size or the allocation granularity int64_t alignment_factor = std::max(static_cast(4096), align_info.allocation_granularity); @@ -4081,6 +4081,10 @@ ONNX_NAMESPACE::GraphProto Graph::ToGraphProtoWithExternalInitializers(const std external_offset = new_external_offset; } + for (size_t index = 0; index != tensor_bytes_size; ++index) { + external_stream << raw_data[index]; + } + output_proto->set_data_location(ONNX_NAMESPACE::TensorProto_DataLocation::TensorProto_DataLocation_EXTERNAL); ONNX_NAMESPACE::StringStringEntryProto* location = output_proto->add_external_data(); location->set_key("location"); From 079295f279800e383d09ecfbaf77fb2f74197090 Mon Sep 17 00:00:00 2001 From: Frank Dong <123416088+frank-dong-ms@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:09:10 -0700 Subject: [PATCH 09/11] refine comments --- include/onnxruntime/core/graph/graph.h | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index 8d7be5884182a..762f0089d0161 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1140,13 +1140,21 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi ONNX_NAMESPACE::GraphProto ToGraphProto() const; // Options to align external initializer offset. + // For models running on CPU, ORT will try to use mmap to load external initializers. + // To use mmap, external initializer need to be offset aligned. + // ORT saves external initializers into signle data file, each initializer is accessed with + // offset(start position of initializer) and length(byte length of initializer) of the data file. + // To use mmap, each offset need to be aligned which means offset need to divisible by + // allocation granularity(64KB for windows and 4K for other OSes). + // With align_offset to true, ORT will align offset for large initializer when + // save ONNX model with external data file. struct OffsetAlignmentInfo { // Offset will always be page aligned and allocation granularity aligned for mmap support. // This is done by padding previous tensor data with zeros keeping same length. bool align_offset = false; // Alignment threshold for size of data. // Having a low threshold will waste file space for small initializers. - // Only when tensor's data is > the page_align_threshold it will be force aligned. + // Only when tensor's data size is > the page_align_threshold it will be force aligned. // Default to 1MB. int64_t align_threshold = 1048576; // The allocation Granularity for mmap() support. From 1f2fe4212f2fa603909f3c1c42cbeb3a4e4bd093 Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Wed, 21 Aug 2024 13:25:19 -0700 Subject: [PATCH 10/11] style fix --- cmake/external/emsdk | 2 +- include/onnxruntime/core/graph/graph.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/external/emsdk b/cmake/external/emsdk index 0fde04880048f..d52c465201248 160000 --- a/cmake/external/emsdk +++ b/cmake/external/emsdk @@ -1 +1 @@ -Subproject commit 0fde04880048f743056bed17cb0543a42e040fae +Subproject commit d52c46520124845b1e0e0525f2759299d840143f diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index 762f0089d0161..994087d985235 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -1146,7 +1146,7 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi // offset(start position of initializer) and length(byte length of initializer) of the data file. // To use mmap, each offset need to be aligned which means offset need to divisible by // allocation granularity(64KB for windows and 4K for other OSes). - // With align_offset to true, ORT will align offset for large initializer when + // With align_offset to true, ORT will align offset for large initializer when // save ONNX model with external data file. struct OffsetAlignmentInfo { // Offset will always be page aligned and allocation granularity aligned for mmap support. From 1eb8ecce8d3eec83238c10412fcce6a19b89e4f8 Mon Sep 17 00:00:00 2001 From: Frank Dong Date: Wed, 21 Aug 2024 17:15:36 -0700 Subject: [PATCH 11/11] rollback emsdk change --- cmake/external/emsdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/external/emsdk b/cmake/external/emsdk index d52c465201248..0fde04880048f 160000 --- a/cmake/external/emsdk +++ b/cmake/external/emsdk @@ -1 +1 @@ -Subproject commit d52c46520124845b1e0e0525f2759299d840143f +Subproject commit 0fde04880048f743056bed17cb0543a42e040fae