Skip to content

Commit ebcd90e

Browse files
authored
make ETDumpGen use bufferdatasink
Differential Revision: D69647096 Pull Request resolved: #8741
1 parent f439d78 commit ebcd90e

File tree

8 files changed

+348
-228
lines changed

8 files changed

+348
-228
lines changed

devtools/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ add_custom_command(
176176
add_library(
177177
etdump ${CMAKE_CURRENT_SOURCE_DIR}/etdump/etdump_flatcc.cpp
178178
${CMAKE_CURRENT_SOURCE_DIR}/etdump/emitter.cpp
179+
${CMAKE_CURRENT_SOURCE_DIR}/etdump/buffer_data_sink.cpp
180+
${CMAKE_CURRENT_SOURCE_DIR}/etdump/buffer_data_sink.h
179181
)
180182

181183
target_link_libraries(

devtools/etdump/buffer_data_sink.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ Result<BufferDataSink> BufferDataSink::create(
2727
return BufferDataSink(buffer, alignment);
2828
}
2929

30+
Result<BufferDataSink>
31+
BufferDataSink::create(void* ptr, size_t size, size_t alignment) noexcept {
32+
return BufferDataSink::create({(uint8_t*)ptr, size}, alignment);
33+
}
34+
3035
Result<size_t> BufferDataSink::write(const void* ptr, size_t length) {
3136
if (length == 0) {
3237
return offset_;

devtools/etdump/buffer_data_sink.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,26 @@ class BufferDataSink : public DataSinkBase {
3939
::executorch::runtime::Span<uint8_t> buffer,
4040
size_t alignment = 64) noexcept;
4141

42+
/**
43+
* Creates a BufferDataSink with a given span buffer.
44+
*
45+
* @param[in] ptr A pointer to the data blob where data will be stored.
46+
* @param[in] size The size of the data blob in bytes.
47+
* @param[in] alignment The alignment requirement for the buffer. It must be
48+
* a power of two and greater than zero. Default is 64.
49+
* @return A Result object containing either:
50+
* - A BufferDataSink object if succees, or
51+
* - An error code indicating the failure reason, if any issue
52+
* occurs during the creation process.
53+
*/
54+
static ::executorch::runtime::Result<BufferDataSink>
55+
create(void* ptr, size_t size, size_t alignment = 64) noexcept;
56+
57+
/**
58+
* Creates a empty BufferDataSink;
59+
*/
60+
BufferDataSink() = default;
61+
4262
// Uncopiable and unassignable to avoid double assignment and free of the
4363
// internal buffer.
4464
BufferDataSink(const BufferDataSink&) = delete;

devtools/etdump/etdump_flatcc.cpp

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <cstring>
1212

13+
#include <executorch/devtools/etdump/buffer_data_sink.h>
1314
#include <executorch/devtools/etdump/emitter.h>
1415
#include <executorch/devtools/etdump/etdump_schema_flatcc_builder.h>
1516
#include <executorch/devtools/etdump/etdump_schema_flatcc_reader.h>
@@ -29,6 +30,7 @@ using ::executorch::runtime::DelegateDebugIdType;
2930
using ::executorch::runtime::EValue;
3031
using ::executorch::runtime::EventTracerEntry;
3132
using ::executorch::runtime::LoggedEValueType;
33+
using ::executorch::runtime::Result;
3234
using ::executorch::runtime::Span;
3335
using ::executorch::runtime::Tag;
3436

@@ -142,6 +144,7 @@ ETDumpGen::~ETDumpGen() {
142144
void ETDumpGen::reset() {
143145
state_ = State::Init;
144146
num_blocks_ = 0;
147+
data_sink_ = nullptr;
145148
flatcc_builder_reset(builder_);
146149
flatbuffers_buffer_start(builder_, etdump_ETDump_file_identifier);
147150
etdump_ETDump_start_as_root_with_size(builder_);
@@ -347,10 +350,10 @@ void ETDumpGen::log_intermediate_output_delegate_helper(
347350
ET_CHECK_MSG(
348351
(name == nullptr) ^ (delegate_debug_index == -1),
349352
"Only name or delegate_debug_index can be valid. Check DelegateMappingBuilder documentation for more details.");
350-
if (debug_buffer_.empty()) {
351-
ET_CHECK_MSG(0, "Must pre-set debug buffer with set_debug_buffer()\n");
352-
return;
353-
}
353+
354+
ET_CHECK_MSG(
355+
data_sink_,
356+
"Must pre-set data sink before logging evalue with set_data_sink() or set_debug_buffer()\n");
354357

355358
check_ready_to_add_events();
356359
int64_t string_id = name != nullptr ? create_string_entry(name) : -1;
@@ -367,7 +370,7 @@ void ETDumpGen::log_intermediate_output_delegate_helper(
367370

368371
// Check the type of `output` then call the corresponding logging functions
369372
if constexpr (std::is_same<T, Tensor>::value) {
370-
long offset = copy_tensor_to_debug_buffer(output);
373+
long offset = write_tensor_or_raise_error(output);
371374
etdump_Tensor_ref_t tensor_ref = add_tensor_entry(builder_, output, offset);
372375

373376
etdump_Value_start(builder_);
@@ -377,7 +380,7 @@ void ETDumpGen::log_intermediate_output_delegate_helper(
377380
} else if constexpr (std::is_same<T, ArrayRef<Tensor>>::value) {
378381
etdump_Tensor_vec_start(builder_);
379382
for (size_t i = 0; i < output.size(); ++i) {
380-
long offset = copy_tensor_to_debug_buffer(output[i]);
383+
long offset = write_tensor_or_raise_error(output[i]);
381384
etdump_Tensor_vec_push(
382385
builder_, add_tensor_entry(builder_, output[i], offset));
383386
}
@@ -497,27 +500,22 @@ ETDumpResult ETDumpGen::get_etdump_data() {
497500
}
498501

499502
void ETDumpGen::set_debug_buffer(Span<uint8_t> buffer) {
500-
debug_buffer_ = buffer;
503+
Result<BufferDataSink> bds_ret = BufferDataSink::create(buffer);
504+
ET_CHECK_MSG(
505+
bds_ret.ok(),
506+
"Failed to write tensor with error 0x%" PRIx32,
507+
static_cast<uint32_t>(bds_ret.error()));
508+
509+
buffer_data_sink_ = std::move(bds_ret.get());
510+
data_sink_ = &buffer_data_sink_;
501511
}
502512

503-
size_t ETDumpGen::copy_tensor_to_debug_buffer(executorch::aten::Tensor tensor) {
504-
if (tensor.nbytes() == 0) {
505-
return static_cast<size_t>(-1);
506-
}
507-
uint8_t* offset_ptr =
508-
internal::align_pointer(debug_buffer_.data() + debug_buffer_offset_, 64);
509-
debug_buffer_offset_ = (offset_ptr - debug_buffer_.data()) + tensor.nbytes();
510-
ET_CHECK_MSG(
511-
debug_buffer_offset_ <= debug_buffer_.size(),
512-
"Ran out of space to store intermediate outputs.");
513-
memcpy(offset_ptr, tensor.const_data_ptr(), tensor.nbytes());
514-
return (size_t)(offset_ptr - debug_buffer_.data());
513+
void ETDumpGen::set_data_sink(DataSinkBase* data_sink) {
514+
data_sink_ = data_sink;
515515
}
516516

517517
void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) {
518-
if (debug_buffer_.empty()) {
519-
return;
520-
}
518+
ET_CHECK_MSG(data_sink_, "Must set data sink before logging evalue\n");
521519

522520
check_ready_to_add_events();
523521

@@ -529,7 +527,7 @@ void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) {
529527
switch (evalue.tag) {
530528
case Tag::Tensor: {
531529
executorch::aten::Tensor tensor = evalue.toTensor();
532-
long offset = copy_tensor_to_debug_buffer(tensor);
530+
long offset = write_tensor_or_raise_error(tensor);
533531
etdump_Tensor_ref_t tensor_ref =
534532
add_tensor_entry(builder_, tensor, offset);
535533

@@ -551,7 +549,7 @@ void ETDumpGen::log_evalue(const EValue& evalue, LoggedEValueType evalue_type) {
551549
evalue.toTensorList();
552550
etdump_Tensor_vec_start(builder_);
553551
for (size_t i = 0; i < tensors.size(); ++i) {
554-
long offset = copy_tensor_to_debug_buffer(tensors[i]);
552+
long offset = write_tensor_or_raise_error(tensors[i]);
555553
etdump_Tensor_vec_push(
556554
builder_, add_tensor_entry(builder_, tensors[i], offset));
557555
}
@@ -635,8 +633,31 @@ bool ETDumpGen::is_static_etdump() {
635633
return alloc_.data != nullptr;
636634
}
637635

638-
size_t ETDumpGen::get_debug_buffer_size() const {
639-
return debug_buffer_.size();
636+
DataSinkBase* ETDumpGen::get_data_sink() {
637+
return data_sink_;
638+
}
639+
640+
long ETDumpGen::write_tensor_or_raise_error(Tensor tensor) {
641+
// Previously, the function copy_tensor_to_debug_buffer returned 0xFF..F when
642+
// given an empty tensor, which is an invalid offset for most buffers. In our
643+
// data sink, we will return the current debug_buffer_offset for better
644+
// clarity. We are isolating the empty tensor case here using the old logic to
645+
// avoid any backward compatibility issues while introducing the data sink.
646+
// Once the data sink is fully implemented, we can remove this check and apply
647+
// the new logic to all cases.
648+
// TODO(gasoonjia): remove this check after datasink is fully rolled out.
649+
if (tensor.nbytes() == 0) {
650+
return static_cast<size_t>(-1);
651+
}
652+
653+
ET_CHECK_MSG(data_sink_, "Must set data sink before writing data");
654+
Result<size_t> ret =
655+
data_sink_->write(tensor.const_data_ptr(), tensor.nbytes());
656+
ET_CHECK_MSG(
657+
ret.ok(),
658+
"Failed to write tensor with error 0x%" PRIx32,
659+
static_cast<uint32_t>(ret.error()));
660+
return static_cast<long>(ret.get());
640661
}
641662

642663
} // namespace etdump

devtools/etdump/etdump_flatcc.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
#pragma once
1010

1111
#include <cstdint>
12+
#include <memory>
1213

14+
#include <executorch/devtools/etdump/buffer_data_sink.h>
15+
#include <executorch/devtools/etdump/data_sink_base.h>
1316
#include <executorch/runtime/core/event_tracer.h>
1417
#include <executorch/runtime/core/span.h>
1518
#include <executorch/runtime/platform/platform.h>
@@ -141,9 +144,10 @@ class ETDumpGen : public ::executorch::runtime::EventTracer {
141144
::executorch::runtime::DebugHandle delegate_debug_index,
142145
const double& output) override;
143146
void set_debug_buffer(::executorch::runtime::Span<uint8_t> buffer);
147+
void set_data_sink(DataSinkBase* data_sink);
144148
ETDumpResult get_etdump_data();
145-
size_t get_debug_buffer_size() const;
146149
size_t get_num_blocks();
150+
DataSinkBase* get_data_sink();
147151
bool is_static_etdump();
148152
void reset();
149153

@@ -158,7 +162,6 @@ class ETDumpGen : public ::executorch::runtime::EventTracer {
158162

159163
void check_ready_to_add_events();
160164
int64_t create_string_entry(const char* name);
161-
size_t copy_tensor_to_debug_buffer(executorch::aten::Tensor tensor);
162165

163166
/**
164167
* Templated helper function used to log various types of intermediate output.
@@ -170,10 +173,15 @@ class ETDumpGen : public ::executorch::runtime::EventTracer {
170173
::executorch::runtime::DebugHandle delegate_debug_index,
171174
const T& output);
172175

176+
long write_tensor_or_raise_error(executorch::aten::Tensor tensor);
177+
173178
struct flatcc_builder* builder_;
174179
size_t num_blocks_ = 0;
175-
::executorch::runtime::Span<uint8_t> debug_buffer_;
176-
size_t debug_buffer_offset_ = 0;
180+
DataSinkBase* data_sink_;
181+
182+
// It is only for set_debug_buffer function.
183+
BufferDataSink buffer_data_sink_;
184+
177185
int bundled_input_index_ = -1;
178186
State state_ = State::Init;
179187
struct internal::ETDumpStaticAllocator alloc_;

devtools/etdump/targets.bzl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def define_common_targets():
117117

118118
runtime.cxx_library(
119119
name = "buffer_data_sink" + aten_suffix,
120-
headers = [
120+
exported_headers = [
121121
"buffer_data_sink.h",
122122
],
123123
srcs = [
@@ -153,6 +153,8 @@ def define_common_targets():
153153
exported_deps = [
154154
":etdump_schema_flatcc",
155155
":utils",
156+
":data_sink_base" + aten_suffix,
157+
":buffer_data_sink" + aten_suffix,
156158
"//executorch/runtime/core:event_tracer" + aten_suffix,
157159
"//executorch/runtime/core/exec_aten/util:scalar_type_util" + aten_suffix,
158160
],

0 commit comments

Comments
 (0)