Skip to content

Commit 6cb5c1a

Browse files
pytorchbotGasoonjiaswolchok
authored
[devtool] introduce datasink class to etdump (#8677)
Pull Request resolved: #8496 this diff introduce datasink class, the class for managing the customized debug data storage pipeline. Detials can be found in https://docs.google.com/document/d/1y_m32mKdj-OgLcLUz9TKhBW3PC3bBDYSBbeAH544EfM/edit?tab=t.0 ghstack-source-id: 268137338 Differential Revision: [D69583422](https://our.internmc.facebook.com/intern/diff/D69583422/) Co-authored-by: gasoonjia <[email protected]> Co-authored-by: Scott Wolchok <[email protected]>
1 parent d7f964a commit 6cb5c1a

File tree

9 files changed

+425
-14
lines changed

9 files changed

+425
-14
lines changed

devtools/etdump/buffer_data_sink.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
#include <executorch/devtools/etdump/buffer_data_sink.h>
10+
#include <executorch/devtools/etdump/utils.h>
11+
12+
using ::executorch::runtime::Error;
13+
using ::executorch::runtime::Result;
14+
15+
namespace executorch {
16+
namespace etdump {
17+
18+
Result<size_t> BufferDataSink::write(const void* ptr, size_t length) {
19+
if (length == 0) {
20+
return offset_;
21+
}
22+
23+
uint8_t* last_data_end = debug_buffer_.data() + offset_;
24+
25+
// The beginning of the next data blob must be aligned to the alignment
26+
uint8_t* cur_data_begin = internal::align_pointer(last_data_end, alignment_);
27+
uint8_t* cur_data_end = cur_data_begin + length;
28+
29+
if (cur_data_end > debug_buffer_.data() + debug_buffer_.size()) {
30+
ET_LOG(Error, "Ran out of space to store intermediate outputs.");
31+
return Error::OutOfResources;
32+
}
33+
34+
// Zero out the padding between data blobs
35+
memset(last_data_end, 0, cur_data_begin - last_data_end);
36+
memcpy(cur_data_begin, ptr, length);
37+
offset_ = (size_t)(cur_data_end - debug_buffer_.data());
38+
39+
return (size_t)(cur_data_begin - debug_buffer_.data());
40+
}
41+
42+
Result<size_t> BufferDataSink::get_storage_size() const {
43+
return debug_buffer_.size();
44+
}
45+
46+
size_t BufferDataSink::get_used_bytes() const {
47+
return offset_;
48+
}
49+
50+
} // namespace etdump
51+
} // namespace executorch

devtools/etdump/buffer_data_sink.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
#pragma once
10+
11+
#include <executorch/devtools/etdump/data_sink_base.h>
12+
#include <executorch/runtime/core/exec_aten/exec_aten.h>
13+
#include <executorch/runtime/core/span.h>
14+
15+
namespace executorch {
16+
namespace etdump {
17+
18+
/**
19+
* BufferDataSink is a concrete implementation of the DataSinkBase class,
20+
* designed to store debug data in a pre-allocated, user-owned buffer. This
21+
* class provides methods to write raw data and tensor data into the buffer,
22+
* ensuring proper alignment and managing padding as needed.
23+
*/
24+
class BufferDataSink : public DataSinkBase {
25+
public:
26+
/**
27+
* Constructs a BufferDataSink with a given buffer.
28+
*
29+
* @param[in] buffer A Span object representing the buffer where data will be
30+
* stored.
31+
* @param[in] alignment The alignment requirement for the buffer. It must be
32+
* a power of two. Default is 64.
33+
*/
34+
explicit BufferDataSink(
35+
::executorch::runtime::Span<uint8_t> buffer,
36+
size_t alignment = 64)
37+
: debug_buffer_(buffer), offset_(0), alignment_(alignment) {}
38+
39+
// Uncopiable and unassignable to avoid double assignment and free of the
40+
// internal buffer.
41+
BufferDataSink(const BufferDataSink&) = delete;
42+
BufferDataSink& operator=(const BufferDataSink&) = delete;
43+
44+
// Movable to be compatible with Result.
45+
BufferDataSink(BufferDataSink&&) = default;
46+
BufferDataSink& operator=(BufferDataSink&&) = default;
47+
48+
~BufferDataSink() override = default;
49+
50+
/**
51+
* Write data into the debug buffer and return the offset of the starting
52+
* location of the data within the buffer.
53+
*
54+
* @param[in] ptr A pointer to the data to be written into the storage.
55+
* @param[in] size The size of the data in bytes.
56+
* @return A Result object containing either:
57+
* - The offset of the starting location of the data within the
58+
* debug buffer, or
59+
* - An error code indicating the failure reason, if any issue
60+
* occurs during the write process.
61+
*/
62+
::executorch::runtime::Result<size_t> write(const void* ptr, size_t size)
63+
override;
64+
65+
/**
66+
* Retrieves the total size of the buffer.
67+
*
68+
* @return A Result object containing the total size of the buffer in bytes.
69+
*/
70+
::executorch::runtime::Result<size_t> get_storage_size() const;
71+
72+
/**
73+
* Retrieves the number of bytes currently used in the buffer.
74+
*
75+
* @return The amount of data currently stored in the buffer in bytes.
76+
*/
77+
size_t get_used_bytes() const override;
78+
79+
private:
80+
// A Span object representing the buffer used for storing debug data.
81+
::executorch::runtime::Span<uint8_t> debug_buffer_;
82+
83+
// The offset of the next available location in the buffer.
84+
size_t offset_;
85+
86+
// The alignment of the buffer.
87+
size_t alignment_;
88+
};
89+
90+
} // namespace etdump
91+
} // namespace executorch

devtools/etdump/data_sink_base.h

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree.
7+
*/
8+
9+
#pragma once
10+
11+
#include <executorch/runtime/core/exec_aten/exec_aten.h>
12+
#include <executorch/runtime/core/result.h>
13+
14+
namespace executorch {
15+
namespace etdump {
16+
17+
/**
18+
* DataSinkBase is an abstract class that users can inherit and implement
19+
* to customize the storage and management of debug data in ETDumpGen. This
20+
* class provides a basic and essential interface for writing datablob to a
21+
* user-defined storage, retrieving storage capacity, and tracking the amount of
22+
* data stored.
23+
*/
24+
class DataSinkBase {
25+
public:
26+
/**
27+
* Virtual destructor to ensure proper cleanup of derived classes.
28+
*/
29+
30+
virtual ~DataSinkBase() = default;
31+
/**
32+
* Write data into the debug storage. This method should be implemented
33+
* by derived classes to handle the specifics of data storage.
34+
*
35+
* This function should return the offset of the starting location of the
36+
* data within the debug storage if the write operation succeeds, or an
37+
* Error code if any issue occurs during the write process.
38+
*
39+
* @param[in] ptr A pointer to the data to be written into the storage.
40+
* @param[in] length The size of the data in bytes.
41+
* @return A Result object containing either:
42+
* - The offset of the starting location of the data within the
43+
* debug storage, which will be recorded in the corresponding
44+
* metadata of ETDump, or
45+
* - An error code indicating the failure reason, if any issue
46+
* occurs during the write process.
47+
*/
48+
virtual ::executorch::runtime::Result<size_t> write(
49+
const void* ptr,
50+
size_t length) = 0;
51+
52+
/**
53+
* Get the number of bytes currently used in the debug storage.
54+
*
55+
* @return The amount of data currently stored in bytes.
56+
*/
57+
virtual size_t get_used_bytes() const = 0;
58+
};
59+
60+
} // namespace etdump
61+
} // namespace executorch

devtools/etdump/etdump_flatcc.cpp

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <executorch/devtools/etdump/emitter.h>
1414
#include <executorch/devtools/etdump/etdump_schema_flatcc_builder.h>
1515
#include <executorch/devtools/etdump/etdump_schema_flatcc_reader.h>
16+
#include <executorch/devtools/etdump/utils.h>
1617
#include <executorch/runtime/core/exec_aten/exec_aten.h>
1718
#include <executorch/runtime/core/exec_aten/util/scalar_type_util.h>
1819
#include <executorch/runtime/platform/assert.h>
@@ -94,16 +95,6 @@ etdump_Tensor_ref_t add_tensor_entry(
9495
return etdump_Tensor_end(builder_);
9596
}
9697

97-
static uint8_t* alignPointer(void* ptr, size_t alignment) {
98-
intptr_t addr = reinterpret_cast<intptr_t>(ptr);
99-
if ((addr & (alignment - 1)) == 0) {
100-
// Already aligned.
101-
return reinterpret_cast<uint8_t*>(ptr);
102-
}
103-
addr = (addr | (alignment - 1)) + 1;
104-
return reinterpret_cast<uint8_t*>(addr);
105-
}
106-
10798
} // namespace
10899

109100
// Constructor implementation
@@ -113,9 +104,10 @@ ETDumpGen::ETDumpGen(Span<uint8_t> buffer) {
113104
// Initialize the flatcc builder_ using the buffer and buffer size.
114105

115106
if (buffer.data() != nullptr) {
116-
builder_ = (struct flatcc_builder*)alignPointer(buffer.data(), 64);
117-
uintptr_t buffer_with_builder =
118-
(uintptr_t)alignPointer(builder_ + sizeof(struct flatcc_builder), 64);
107+
builder_ =
108+
(struct flatcc_builder*)internal::align_pointer(buffer.data(), 64);
109+
uintptr_t buffer_with_builder = (uintptr_t)internal::align_pointer(
110+
builder_ + sizeof(struct flatcc_builder), 64);
119111
size_t builder_size =
120112
(size_t)(buffer_with_builder - (uintptr_t)buffer.data());
121113
size_t min_buf_size = max_alloc_buf_size + builder_size;
@@ -513,7 +505,7 @@ size_t ETDumpGen::copy_tensor_to_debug_buffer(executorch::aten::Tensor tensor) {
513505
return static_cast<size_t>(-1);
514506
}
515507
uint8_t* offset_ptr =
516-
alignPointer(debug_buffer_.data() + debug_buffer_offset_, 64);
508+
internal::align_pointer(debug_buffer_.data() + debug_buffer_offset_, 64);
517509
debug_buffer_offset_ = (offset_ptr - debug_buffer_.data()) + tensor.nbytes();
518510
ET_CHECK_MSG(
519511
debug_buffer_offset_ <= debug_buffer_.size(),

devtools/etdump/targets.bzl

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,54 @@ def define_common_targets():
8787
exported_external_deps = ["flatccrt"],
8888
)
8989

90+
runtime.cxx_library(
91+
name = "utils",
92+
srcs = [],
93+
exported_headers = [
94+
"utils.h",
95+
],
96+
visibility = [
97+
98+
],
99+
)
100+
90101
for aten_mode in get_aten_mode_options():
91102
aten_suffix = "_aten" if aten_mode else ""
103+
104+
runtime.cxx_library(
105+
name = "data_sink_base" + aten_suffix,
106+
exported_headers = [
107+
"data_sink_base.h",
108+
],
109+
exported_deps = [
110+
"//executorch/runtime/core/exec_aten/util:scalar_type_util" + aten_suffix,
111+
],
112+
visibility = [
113+
"//executorch/...",
114+
"@EXECUTORCH_CLIENTS",
115+
],
116+
)
117+
118+
runtime.cxx_library(
119+
name = "buffer_data_sink" + aten_suffix,
120+
headers = [
121+
"buffer_data_sink.h",
122+
],
123+
srcs = [
124+
"buffer_data_sink.cpp",
125+
],
126+
deps = [
127+
":utils",
128+
],
129+
exported_deps = [
130+
"//executorch/runtime/core/exec_aten:lib" + aten_suffix,
131+
":data_sink_base" + aten_suffix,
132+
],
133+
visibility = [
134+
"//executorch/...",
135+
"@EXECUTORCH_CLIENTS",
136+
],
137+
)
92138
runtime.cxx_library(
93139
name = "etdump_flatcc" + aten_suffix,
94140
srcs = [
@@ -106,6 +152,7 @@ def define_common_targets():
106152
],
107153
exported_deps = [
108154
":etdump_schema_flatcc",
155+
":utils",
109156
"//executorch/runtime/core:event_tracer" + aten_suffix,
110157
"//executorch/runtime/core/exec_aten/util:scalar_type_util" + aten_suffix,
111158
],

0 commit comments

Comments
 (0)