Skip to content

Commit a7714e3

Browse files
committed
[ET Device Support] DeviceAllocator interface and DeviceAllocatorRegistry
Pull Request resolved: #17535 This diff introduces the `DeviceAllocator` abstract interface and `DeviceAllocatorRegistry` for device-specific memory allocation. This is a foundational abstraction that enables the runtime to dispatch memory operations to the appropriate device backend other than CPU (CUDA, etc.). **DeviceAllocator interface provides:** - `allocate()` / `deallocate()` - Dynamic device memory allocation - `copy_host_to_device()` / `copy_device_to_host()` - Data transfer between host and device - `device_type()` - Returns the device type this allocator handles **DeviceAllocatorRegistry provides:** - Singleton registry mapping DeviceType → DeviceAllocator - `register_allocator()` / `get_allocator()` methods - Fixed-size array indexed by device type (no dynamic allocation, embedded-friendly) **Design notes:** - Registry stores raw pointers (non-owning) - allocators are expected to be singletons with static lifetime - Follows ExecuTorch's embedded-first philosophy (no std::unique_ptr, no heap allocation in registry) - Convenience free functions `register_device_allocator()` and `get_device_allocator()` for ease of use ghstack-source-id: 354740821 Differential Revision: [D93635656](https://our.internmc.facebook.com/intern/diff/D93635656/)
1 parent 33eb0d5 commit a7714e3

3 files changed

Lines changed: 421 additions & 0 deletions

File tree

runtime/core/device_allocator.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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/runtime/core/device_allocator.h>
10+
11+
#include <executorch/runtime/platform/assert.h>
12+
13+
namespace executorch {
14+
namespace runtime {
15+
16+
DeviceAllocatorRegistry& DeviceAllocatorRegistry::instance() {
17+
static DeviceAllocatorRegistry registry;
18+
return registry;
19+
}
20+
21+
void DeviceAllocatorRegistry::register_allocator(
22+
etensor::DeviceType type,
23+
DeviceAllocator* alloc) {
24+
auto index = static_cast<size_t>(type);
25+
ET_CHECK_MSG(
26+
index < etensor::kNumDeviceTypes,
27+
"Invalid device type: %d",
28+
static_cast<int>(type));
29+
ET_CHECK_MSG(
30+
allocators_[index] == nullptr,
31+
"Allocator already registered for device type: %d",
32+
static_cast<int>(type));
33+
allocators_[index] = alloc;
34+
}
35+
36+
DeviceAllocator* DeviceAllocatorRegistry::get_allocator(
37+
etensor::DeviceType type) {
38+
auto index = static_cast<size_t>(type);
39+
if (index >= etensor::kNumDeviceTypes) {
40+
return nullptr;
41+
}
42+
return allocators_[index];
43+
}
44+
45+
// Convenience free functions
46+
47+
void register_device_allocator(
48+
etensor::DeviceType type,
49+
DeviceAllocator* alloc) {
50+
DeviceAllocatorRegistry::instance().register_allocator(type, alloc);
51+
}
52+
53+
DeviceAllocator* get_device_allocator(etensor::DeviceType type) {
54+
return DeviceAllocatorRegistry::instance().get_allocator(type);
55+
}
56+
57+
} // namespace runtime
58+
} // namespace executorch

runtime/core/device_allocator.h

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
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 <cstddef>
12+
13+
#include <executorch/runtime/core/error.h>
14+
#include <executorch/runtime/core/portable_type/device.h>
15+
#include <executorch/runtime/core/result.h>
16+
17+
namespace executorch {
18+
namespace runtime {
19+
20+
/**
21+
* Abstract interface for device-specific memory allocation.
22+
*
23+
* Each device type (CUDA, etc.) provides a concrete implementation
24+
* that handles memory allocation on that device. Implementations are
25+
* expected to be singletons with static lifetime, registered via
26+
* DeviceAllocatorRegistry.
27+
28+
*/
29+
class DeviceAllocator {
30+
public:
31+
virtual ~DeviceAllocator() = default;
32+
/**
33+
* Allocate device memory.
34+
*
35+
* @param nbytes Number of bytes to allocate.
36+
* @param index The device index.
37+
* @return A Result containing the device pointer on success, or an error.
38+
*/
39+
virtual Result<void*> allocate(size_t nbytes, etensor::DeviceIndex index) = 0;
40+
41+
/**
42+
* Deallocate device memory previously allocated via allocate().
43+
*
44+
* @param ptr Pointer to the memory to deallocate.
45+
* @param index The device index.
46+
*/
47+
virtual void deallocate(void* ptr, etensor::DeviceIndex index) = 0;
48+
49+
/**
50+
* Copy data from host memory to device memory.
51+
*
52+
* @param dst Destination pointer (device memory).
53+
* @param src Source pointer (host memory).
54+
* @param nbytes Number of bytes to copy.
55+
* @param index The device index.
56+
* @return Error::Ok on success, or an appropriate error code on failure.
57+
*/
58+
virtual Error copy_host_to_device(
59+
void* dst,
60+
const void* src,
61+
size_t nbytes,
62+
etensor::DeviceIndex index) = 0;
63+
64+
/**
65+
* Copy data from device memory to host memory.
66+
*
67+
* @param dst Destination pointer (host memory).
68+
* @param src Source pointer (device memory).
69+
* @param nbytes Number of bytes to copy.
70+
* @param index The device index.
71+
* @return Error::Ok on success, or an appropriate error code on failure.
72+
*/
73+
virtual Error copy_device_to_host(
74+
void* dst,
75+
const void* src,
76+
size_t nbytes,
77+
etensor::DeviceIndex index) = 0;
78+
79+
/**
80+
* Returns the device type this allocator handles.
81+
*/
82+
virtual etensor::DeviceType device_type() const = 0;
83+
};
84+
85+
/**
86+
* Registry for device allocators.
87+
*
88+
* Provides a global mapping from DeviceType to DeviceAllocator instances.
89+
* Device allocators register themselves at static initialization time,
90+
* and the runtime queries the registry to find the appropriate allocator
91+
* for a given device type.
92+
*/
93+
class DeviceAllocatorRegistry {
94+
public:
95+
/**
96+
* Returns the singleton instance of the registry.
97+
*/
98+
static DeviceAllocatorRegistry& instance();
99+
100+
/**
101+
* Register an allocator for a specific device type.
102+
*
103+
* @param type The device type this allocator handles.
104+
* @param alloc Pointer to the allocator (must have static lifetime).
105+
*/
106+
void register_allocator(etensor::DeviceType type, DeviceAllocator* alloc);
107+
108+
/**
109+
* Get the allocator for a specific device type.
110+
*
111+
* @param type The device type.
112+
* @return Pointer to the allocator, or nullptr if not registered.
113+
*/
114+
DeviceAllocator* get_allocator(etensor::DeviceType type);
115+
116+
private:
117+
DeviceAllocatorRegistry() = default;
118+
119+
// Fixed-size array indexed by device type. This avoids dynamic allocation
120+
// and is suitable for embedded environments.
121+
DeviceAllocator* allocators_[etensor::kNumDeviceTypes] = {};
122+
};
123+
124+
// Convenience free functions
125+
126+
/**
127+
* Register a device allocator for a specific device type.
128+
*
129+
* @param type The device type this allocator handles.
130+
* @param alloc Pointer to the allocator (must have static lifetime).
131+
*/
132+
void register_device_allocator(
133+
etensor::DeviceType type,
134+
DeviceAllocator* alloc);
135+
136+
/**
137+
* Get the device allocator for a specific device type.
138+
*
139+
* @param type The device type.
140+
* @return Pointer to the allocator, or nullptr if not registered.
141+
*/
142+
DeviceAllocator* get_device_allocator(etensor::DeviceType type);
143+
144+
} // namespace runtime
145+
} // namespace executorch
146+
147+
namespace torch {
148+
namespace executor {
149+
// TODO(T197294990): Remove these deprecated aliases once all users have moved
150+
// to the new `::executorch` namespaces.
151+
using ::executorch::runtime::DeviceAllocator;
152+
using ::executorch::runtime::DeviceAllocatorRegistry;
153+
using ::executorch::runtime::get_device_allocator;
154+
using ::executorch::runtime::register_device_allocator;
155+
} // namespace executor
156+
} // namespace torch

0 commit comments

Comments
 (0)