Skip to content

Commit 38f53e8

Browse files
authored
[Hexagon] [runtime] Improve runtime resource management (#12727)
* First pass at improving runtime resource management * Add unit test * Fix lint and clang format errors * Disable resource reset for simulator * Moved acquire/release calls to session object, separate buffer managers for non-runtime (static) and runtime (dynamic). * Fix lint errors * Fix lint errors * Improve robustness of session shutdown * Fix lint * Address feedback * Only allow call to Acquire in a clean state * Use a pointer to indicate the "active" manager
1 parent bb80f19 commit 38f53e8

File tree

4 files changed

+76
-10
lines changed

4 files changed

+76
-10
lines changed

python/tvm/contrib/hexagon/session.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,25 @@ def __enter__(self):
8888
self._rpc_receive_buffer_size_bytes,
8989
],
9090
)
91+
func = self._rpc.get_function("device_api.hexagon.acquire_resources")
92+
func()
9193
return self
9294

9395
except RuntimeError as exception:
9496
raise exception
9597

9698
def __exit__(self, exc_type, exc_value, exc_traceback):
97-
# close session to the tracker
98-
del self._rpc
99+
try:
100+
func = self._rpc.get_function("device_api.hexagon.release_resources")
101+
func()
102+
except RuntimeError as exception:
103+
print(
104+
"Exception occurred while calling release_resources() during Session __exit__: ",
105+
exception,
106+
)
107+
finally:
108+
# close session to the tracker
109+
del self._rpc
99110

100111
@property
101112
def device(self):

src/runtime/hexagon/hexagon_device_api.cc

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,16 +92,16 @@ void* HexagonDeviceAPI::AllocDataSpace(Device dev, int ndim, const int64_t* shap
9292

9393
if (ndim == 0) {
9494
// Allocate storage for a single scalar value.
95-
return hexbuffs.AllocateHexagonBuffer(typesize, kHexagonAllocAlignment, mem_scope);
95+
return mgr->AllocateHexagonBuffer(typesize, kHexagonAllocAlignment, mem_scope);
9696
} else if (ndim == 1) {
9797
// Allocate a single, contiguous memory region.
9898
size_t nbytes = shape[0] * typesize;
99-
return hexbuffs.AllocateHexagonBuffer(nbytes, kHexagonAllocAlignment, mem_scope);
99+
return mgr->AllocateHexagonBuffer(nbytes, kHexagonAllocAlignment, mem_scope);
100100
} else if (ndim == 2) {
101101
// Allocate the region(s) needed for Hexagon's indirect-tensor format.
102102
size_t nallocs = shape[0];
103103
size_t nbytes = shape[1] * typesize;
104-
return hexbuffs.AllocateHexagonBuffer(nallocs, nbytes, kHexagonAllocAlignment, mem_scope);
104+
return mgr->AllocateHexagonBuffer(nallocs, nbytes, kHexagonAllocAlignment, mem_scope);
105105
} else {
106106
return nullptr; // unreachable
107107
}
@@ -115,13 +115,13 @@ void* HexagonDeviceAPI::AllocDataSpace(Device dev, size_t nbytes, size_t alignme
115115
if (alignment < kHexagonAllocAlignment) {
116116
alignment = kHexagonAllocAlignment;
117117
}
118-
return hexbuffs.AllocateHexagonBuffer(nbytes, alignment, String("global"));
118+
return mgr->AllocateHexagonBuffer(nbytes, alignment, String("global"));
119119
}
120120

121121
void HexagonDeviceAPI::FreeDataSpace(Device dev, void* ptr) {
122122
CHECK(ptr) << "buffer pointer is null";
123123
CHECK(IsValidDevice(dev)) << "dev.device_type: " << dev.device_type;
124-
hexbuffs.FreeHexagonBuffer(ptr);
124+
mgr->FreeHexagonBuffer(ptr);
125125
}
126126

127127
// WorkSpace: runtime allocations for Hexagon
@@ -137,7 +137,7 @@ void* HexagonDeviceAPI::AllocWorkspace(Device dev, size_t size, DLDataType type_
137137

138138
void HexagonDeviceAPI::FreeWorkspace(Device dev, void* data) {
139139
CHECK(IsValidDevice(dev)) << "dev.device_type: " << dev.device_type;
140-
CHECK(hexbuffs.count(data) != 0)
140+
CHECK(mgr->count(data) != 0)
141141
<< "Attempt made to free unknown or already freed workspace allocation";
142142
dmlc::ThreadLocalStore<HexagonWorkspacePool>::Get()->FreeWorkspace(dev, data);
143143
}
@@ -161,7 +161,7 @@ void HexagonDeviceAPI::CopyDataFromTo(DLTensor* from, DLTensor* to, TVMStreamHan
161161
CHECK_EQ(to->byte_offset, 0);
162162
CHECK_EQ(GetDataSize(*from), GetDataSize(*to));
163163

164-
auto lookup_hexagon_buffer = [this](void* ptr) -> HexagonBuffer* { return hexbuffs.find(ptr); };
164+
auto lookup_hexagon_buffer = [this](void* ptr) -> HexagonBuffer* { return mgr->find(ptr); };
165165

166166
HexagonBuffer* hex_from_buf = lookup_hexagon_buffer(from->data);
167167
HexagonBuffer* hex_to_buf = lookup_hexagon_buffer(to->data);
@@ -246,6 +246,18 @@ TVM_REGISTER_GLOBAL("device_api.hexagon.free_nd").set_body([](TVMArgs args, TVMR
246246
*rv = static_cast<int32_t>(0);
247247
});
248248

249+
TVM_REGISTER_GLOBAL("device_api.hexagon.acquire_resources")
250+
.set_body([](TVMArgs args, TVMRetValue* rv) {
251+
HexagonDeviceAPI* api = HexagonDeviceAPI::Global();
252+
api->AcquireResources();
253+
});
254+
255+
TVM_REGISTER_GLOBAL("device_api.hexagon.release_resources")
256+
.set_body([](TVMArgs args, TVMRetValue* rv) {
257+
HexagonDeviceAPI* api = HexagonDeviceAPI::Global();
258+
api->ReleaseResources();
259+
});
260+
249261
TVM_REGISTER_GLOBAL("device_api.hexagon").set_body([](TVMArgs args, TVMRetValue* rv) {
250262
DeviceAPI* ptr = HexagonDeviceAPI::Global();
251263
*rv = static_cast<void*>(ptr);

src/runtime/hexagon/hexagon_device_api.h

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,29 @@ class HexagonDeviceAPI final : public DeviceAPI {
4545
static HexagonDeviceAPI* Global();
4646

4747
//! \brief Constructor
48-
HexagonDeviceAPI() {}
48+
HexagonDeviceAPI() { mgr = &hexbuffs; }
4949

5050
//! \brief Destructor
5151
~HexagonDeviceAPI() {}
5252

53+
//! \brief Ensures resource managers are in a good state for the runtime
54+
void AcquireResources() {
55+
CHECK_EQ(runtime_hexbuffs, nullptr);
56+
runtime_hexbuffs = std::make_unique<HexagonBufferManager>();
57+
LOG(INFO) << "runtime_hexbuffs created";
58+
mgr = runtime_hexbuffs.get();
59+
}
60+
61+
//! \brief Ensures all runtime resources are freed
62+
void ReleaseResources() {
63+
if (runtime_hexbuffs && !runtime_hexbuffs->empty()) {
64+
LOG(INFO) << "runtime_hexbuffs was not empty in ReleaseResources";
65+
}
66+
mgr = &hexbuffs;
67+
LOG(INFO) << "runtime_hexbuffs reset";
68+
runtime_hexbuffs.reset();
69+
}
70+
5371
/*! \brief Currently unimplemented interface to specify the active
5472
* Hexagon device.
5573
*/
@@ -138,7 +156,14 @@ class HexagonDeviceAPI final : public DeviceAPI {
138156
}
139157

140158
//! \brief Manages underlying HexagonBuffer allocations
159+
// runtime_hexbuffs is used for runtime allocations. It is created
160+
// with a call to AcquireResources, and destroyed on ReleaseResources.
161+
// hexbuffs is used for all allocations outside of the session lifetime.
141162
HexagonBufferManager hexbuffs;
163+
std::unique_ptr<HexagonBufferManager> runtime_hexbuffs;
164+
165+
//! \brief Current buffer manager
166+
HexagonBufferManager* mgr;
142167
};
143168
} // namespace hexagon
144169
} // namespace runtime

tests/cpp-runtime/hexagon/hexagon_device_api_tests.cc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,21 @@ TEST_F(HexagonDeviceAPITest, DISABLED_alloc_free_diff_dev) {
146146
CHECK(buf != nullptr);
147147
EXPECT_THROW(hexapi->FreeDataSpace(cpu_dev, buf), InternalError);
148148
}
149+
150+
// Alloc a non-runtime buffer
151+
// Alloc a runtime buffer
152+
// "Release" resources for runtime
153+
// Verify the runtime buffer cannot be freed, but the non-runtime buffer can
154+
// This test should be run last
155+
TEST_F(HexagonDeviceAPITest, leak_resources) {
156+
hexapi->ReleaseResources();
157+
void* pre_runtime_buf = hexapi->AllocDataSpace(hex_dev, nbytes, alignment, int8);
158+
CHECK(pre_runtime_buf != nullptr);
159+
hexapi->AcquireResources();
160+
void* runtime_buf = hexapi->AllocDataSpace(hex_dev, nbytes, alignment, int8);
161+
CHECK(runtime_buf != nullptr);
162+
hexapi->ReleaseResources();
163+
EXPECT_THROW(hexapi->FreeDataSpace(hex_dev, runtime_buf), InternalError);
164+
hexapi->FreeDataSpace(hex_dev, pre_runtime_buf);
165+
hexapi->AcquireResources();
166+
}

0 commit comments

Comments
 (0)