-
Notifications
You must be signed in to change notification settings - Fork 712
[devtool] make ETDumpGen use datasink #8499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
e5955e7
9bfa193
9ed69ae
ec95cb0
7c15e29
4328491
a25d258
2f7afb0
56f334c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,6 +10,7 @@ | |
|
|
||
| #include <cstring> | ||
|
|
||
| #include <executorch/devtools/etdump/buffer_data_sink.h> | ||
| #include <executorch/devtools/etdump/emitter.h> | ||
| #include <executorch/devtools/etdump/etdump_schema_flatcc_builder.h> | ||
| #include <executorch/devtools/etdump/etdump_schema_flatcc_reader.h> | ||
|
|
@@ -29,6 +30,7 @@ using ::executorch::runtime::DelegateDebugIdType; | |
| using ::executorch::runtime::EValue; | ||
| using ::executorch::runtime::EventTracerEntry; | ||
| using ::executorch::runtime::LoggedEValueType; | ||
| using ::executorch::runtime::Result; | ||
| using ::executorch::runtime::Span; | ||
| using ::executorch::runtime::Tag; | ||
|
|
||
|
|
@@ -347,10 +349,10 @@ void ETDumpGen::log_intermediate_output_delegate_helper( | |
| ET_CHECK_MSG( | ||
| (name == nullptr) ^ (delegate_debug_index == -1), | ||
| "Only name or delegate_debug_index can be valid. Check DelegateMappingBuilder documentation for more details."); | ||
| if (debug_buffer_.empty()) { | ||
| ET_CHECK_MSG(0, "Must pre-set debug buffer with set_debug_buffer()\n"); | ||
| return; | ||
| } | ||
|
|
||
| ET_CHECK_MSG( | ||
| data_sink_, | ||
| "Must pre-set data sink before logging evalue with set_data_sink() or set_debug_buffer()\n"); | ||
|
|
||
| check_ready_to_add_events(); | ||
| int64_t string_id = name != nullptr ? create_string_entry(name) : -1; | ||
|
|
@@ -367,7 +369,7 @@ void ETDumpGen::log_intermediate_output_delegate_helper( | |
|
|
||
| // Check the type of `output` then call the corresponding logging functions | ||
| if constexpr (std::is_same<T, Tensor>::value) { | ||
| long offset = copy_tensor_to_debug_buffer(output); | ||
| long offset = write_tensor_or_raise_error(output); | ||
| etdump_Tensor_ref_t tensor_ref = add_tensor_entry(builder_, output, offset); | ||
|
|
||
| etdump_Value_start(builder_); | ||
|
|
@@ -377,7 +379,7 @@ void ETDumpGen::log_intermediate_output_delegate_helper( | |
| } else if constexpr (std::is_same<T, ArrayRef<Tensor>>::value) { | ||
| etdump_Tensor_vec_start(builder_); | ||
| for (size_t i = 0; i < output.size(); ++i) { | ||
| long offset = copy_tensor_to_debug_buffer(output[i]); | ||
| long offset = write_tensor_or_raise_error(output[i]); | ||
| etdump_Tensor_vec_push( | ||
| builder_, add_tensor_entry(builder_, output[i], offset)); | ||
| } | ||
|
|
@@ -497,27 +499,15 @@ ETDumpResult ETDumpGen::get_etdump_data() { | |
| } | ||
|
|
||
| void ETDumpGen::set_debug_buffer(Span<uint8_t> buffer) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just for BC. Currently all our users use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually we should keep this API around i think. Only users who want to do their custom thing should know about data sinks, otherwise most users should just be able to call There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. User only need standard data dumping pipeline can use both datasink and |
||
| debug_buffer_ = buffer; | ||
| data_sink_ = std::make_shared<BufferDataSink>(buffer); | ||
|
||
| } | ||
|
|
||
| size_t ETDumpGen::copy_tensor_to_debug_buffer(executorch::aten::Tensor tensor) { | ||
| if (tensor.nbytes() == 0) { | ||
| return static_cast<size_t>(-1); | ||
| } | ||
| uint8_t* offset_ptr = | ||
| internal::alignPointer(debug_buffer_.data() + debug_buffer_offset_, 64); | ||
| debug_buffer_offset_ = (offset_ptr - debug_buffer_.data()) + tensor.nbytes(); | ||
| ET_CHECK_MSG( | ||
| debug_buffer_offset_ <= debug_buffer_.size(), | ||
| "Ran out of space to store intermediate outputs."); | ||
| memcpy(offset_ptr, tensor.const_data_ptr(), tensor.nbytes()); | ||
| return (size_t)(offset_ptr - debug_buffer_.data()); | ||
| void ETDumpGen::set_data_sink(std::shared_ptr<DataSinkBase> buffer_data_sink) { | ||
| data_sink_ = buffer_data_sink; | ||
| } | ||
|
|
||
| void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) { | ||
| if (debug_buffer_.empty()) { | ||
| return; | ||
| } | ||
| ET_CHECK_MSG(data_sink_, "Must set data sink before logging evalue\n"); | ||
|
|
||
| check_ready_to_add_events(); | ||
|
|
||
|
|
@@ -529,7 +519,7 @@ void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) { | |
| switch (evalue.tag) { | ||
| case Tag::Tensor: { | ||
| executorch::aten::Tensor tensor = evalue.toTensor(); | ||
| long offset = copy_tensor_to_debug_buffer(tensor); | ||
| long offset = write_tensor_or_raise_error(tensor); | ||
| etdump_Tensor_ref_t tensor_ref = | ||
| add_tensor_entry(builder_, tensor, offset); | ||
|
|
||
|
|
@@ -551,7 +541,7 @@ void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) { | |
| evalue.toTensorList(); | ||
| etdump_Tensor_vec_start(builder_); | ||
| for (size_t i = 0; i < tensors.size(); ++i) { | ||
| long offset = copy_tensor_to_debug_buffer(tensors[i]); | ||
| long offset = write_tensor_or_raise_error(tensors[i]); | ||
| etdump_Tensor_vec_push( | ||
| builder_, add_tensor_entry(builder_, tensors[i], offset)); | ||
| } | ||
|
|
@@ -636,7 +626,28 @@ bool ETDumpGen::is_static_etdump() { | |
| } | ||
|
|
||
| size_t ETDumpGen::get_debug_buffer_size() const { | ||
| return debug_buffer_.size(); | ||
| return ETDumpGen::get_data_sink_size(); | ||
| } | ||
|
|
||
| size_t ETDumpGen::get_data_sink_size() const { | ||
| ET_CHECK_MSG(data_sink_, "Must set data sink before checking its size\n"); | ||
| Result<size_t> ret = data_sink_->get_storage_size(); | ||
| ET_CHECK_MSG( | ||
| ret.ok(), | ||
| "Failed to get storage size with error 0x%" PRIx32, | ||
| static_cast<uint32_t>(ret.error())); | ||
| return ret.get(); | ||
| } | ||
|
|
||
| long ETDumpGen::write_tensor_or_raise_error(Tensor tensor) { | ||
| ET_CHECK_MSG(data_sink_, "Must set data sink before writing data\n"); | ||
|
||
| Result<size_t> ret = | ||
| data_sink_->write(tensor.const_data_ptr(), tensor.nbytes()); | ||
| ET_CHECK_MSG( | ||
| ret.ok(), | ||
| "Failed to write tensor with error 0x%" PRIx32, | ||
| static_cast<uint32_t>(ret.error())); | ||
| return static_cast<long>(ret.get()); | ||
| } | ||
|
|
||
| } // namespace etdump | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there internal users who need this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not right now but introducing this constructor may make our friends life easier and I'd like to make it as a primary entrance in the future
If our user contructs
BufferDataSinkfrom Span:However if from the new constructor:
More straightforward and sturcure, user doesn't need to take care about span or anything else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that the Span ctor would work with syntax like
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Program syntactically yes, but user need to figure out what's span is, how to construct it, and how to make the logic shorter, which introduces lots of ramp up cost.
Put into user's shoe, they don't need to knwo what span is. A buffer data sink should be directly constructed on the user-provided memory space, and all type transforming should be happened under-the-neath.