forked from iree-org/iree
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdevice_manager.h
150 lines (132 loc) · 6.75 KB
/
device_manager.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_MLIR_EDGE_IREE_HAL_DEVICE_MANAGER_H_
#define THIRD_PARTY_MLIR_EDGE_IREE_HAL_DEVICE_MANAGER_H_
#include <vector>
#include "third_party/absl/synchronization/mutex.h"
#include "third_party/absl/types/span.h"
#include "third_party/mlir_edge/iree/base/status.h"
#include "third_party/mlir_edge/iree/hal/allocator.h"
#include "third_party/mlir_edge/iree/hal/buffer.h"
#include "third_party/mlir_edge/iree/hal/device.h"
#include "third_party/mlir_edge/iree/hal/device_placement.h"
#include "third_party/mlir_edge/iree/hal/executable_format.h"
namespace iree {
namespace hal {
// Specifies how devices should be resolved to DevicePlacements.
// Most fields are optional and when not included will be ignored.
struct PlacementSpec {
// TODO(benvanik): other requirements (features/caps, power, etc).
// A list of executable formats that the placement should support.
// If more than one format is provided any device satisfying at least one
// will be considered for placement. The formats can be sorted in descending
// priority order to prefer the first available format in the case of ties.
absl::Span<const ExecutableFormat> available_formats;
};
// Manages device lifetime and placement resolution.
//
// Thread-safe. Note that callers must ensure that unregistered devices are kept
// alive for as long as any commands are in-flight that may be using them.
class DeviceManager final {
public:
DeviceManager();
~DeviceManager();
// Registers a device with the manager.
// The device will be used to resolve placements. Any placements resolved
// prior to the addition of the device will need to be refreshed by the caller
// if they want to make use of the new device.
Status RegisterDevice(std::shared_ptr<Device> device);
// Unregisters a device with the manager.
// Placements that resolved to the device prior to unregistering will remain
// valid for that device. Callers will need to refresh the placements to
// ensure the device stops being used.
Status UnregisterDevice(Device* device);
// TODO(benvanik): dispatch info + requirements + etc -> DevicePlacement.
// Resolves a placement spec to a device placement based on the registered
// devices.
// If the placement is not fully specified the device and queue may be chosen
// at random. See PlacementSpec for more information about resolution and
// ranking.
StatusOr<DevicePlacement> ResolvePlacement(
const PlacementSpec& placement_spec) const;
// Finds an allocator that can allocate buffers of the given |memory_type| and
// |buffer_usage| such that the buffers can be used interchangebly.
// Fails if there is no Allocator that can satisfy that requirement.
StatusOr<Allocator*> FindCompatibleAllocator(
MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
absl::Span<const DevicePlacement> device_placements) const;
// Tries to allocate a host-local buffer that _may_ be optimal for use with
// the given |device_placements| and _may_ be device-visible. The buffer can
// be used for staging uploads to device-local buffers and is useful for times
// when the buffer will be used more on the host than the device. If a buffer
// never needs to be used with a device prefer instead
// Allocator::host_local()::Allocate.
//
// Returns a buffer even if it's not possible to satisfy the requested
// |buffer_usage| for the |device_placements| at the cost of a run-time
// performance hit.
StatusOr<ref_ptr<Buffer>> TryAllocateDeviceVisibleBuffer(
MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
device_size_t allocation_size,
absl::Span<const DevicePlacement> device_placements);
StatusOr<ref_ptr<Buffer>> TryAllocateDeviceVisibleBuffer(
BufferUsageBitfield buffer_usage, device_size_t allocation_size,
absl::Span<const DevicePlacement> device_placements) {
return TryAllocateDeviceVisibleBuffer(
MemoryType::kHostLocal | MemoryType::kDeviceVisible, buffer_usage,
allocation_size, device_placements);
}
// Allocates a host-local buffer that is optimal for use on the host but is
// usable by the given |device_placements| (at a possible performance
// penalty). The buffer can be used for staging uploads to device-local
// buffers and is useful for times when the buffer will be used more on the
// host than the device. If a buffer never needs to be used with a device
// prefer instead HeapBuffer::Allocate.
//
// Fails if it is not possible to allocate and satisfy all |device_placements|
// for the requested |buffer_usage|.
StatusOr<ref_ptr<Buffer>> AllocateDeviceVisibleBuffer(
MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
device_size_t allocation_size,
absl::Span<const DevicePlacement> device_placements);
StatusOr<ref_ptr<Buffer>> AllocateDeviceVisibleBuffer(
BufferUsageBitfield buffer_usage, device_size_t allocation_size,
absl::Span<const DevicePlacement> device_placements) {
return AllocateDeviceVisibleBuffer(
MemoryType::kHostLocal | MemoryType::kDeviceVisible, buffer_usage,
allocation_size, device_placements);
}
// Allocates a device-local buffer that is optimal for use with the given
// |device_placements|. The buffer will not be host-visible and can only be
// used from compatible device queues.
//
// Fails if it is not possible to allocate and satisfy all |device_placements|
// for the requested |buffer_usage|.
StatusOr<ref_ptr<Buffer>> AllocateDeviceLocalBuffer(
MemoryTypeBitfield memory_type, BufferUsageBitfield buffer_usage,
device_size_t allocation_size,
absl::Span<const DevicePlacement> device_placements);
StatusOr<ref_ptr<Buffer>> AllocateDeviceLocalBuffer(
BufferUsageBitfield buffer_usage, device_size_t allocation_size,
absl::Span<const DevicePlacement> device_placements) {
return AllocateDeviceLocalBuffer(MemoryType::kDeviceLocal, buffer_usage,
allocation_size, device_placements);
}
private:
mutable absl::Mutex device_mutex_;
std::vector<std::shared_ptr<Device>> devices_ ABSL_GUARDED_BY(device_mutex_);
};
} // namespace hal
} // namespace iree
#endif // THIRD_PARTY_MLIR_EDGE_IREE_HAL_DEVICE_MANAGER_H_