9
9
// ===----------------------------------------------------------------------===//
10
10
#pragma once
11
11
12
- #include " common.hpp"
13
12
#include " context.hpp"
14
13
#include " event.hpp"
15
14
#include < cassert>
15
+ #include < memory>
16
+ #include < unordered_map>
16
17
#include < variant>
17
18
19
+ #include " common.hpp"
20
+
18
21
ur_result_t allocateMemObjOnDeviceIfNeeded (ur_mem_handle_t ,
19
22
const ur_device_handle_t );
20
23
ur_result_t migrateMemoryToDeviceIfNeeded (ur_mem_handle_t ,
21
24
const ur_device_handle_t );
22
25
23
26
// Handler for plain, pointer-based HIP allocations
24
27
struct BufferMem {
28
+ struct BufferMap {
29
+ // / Size of the active mapped region.
30
+ size_t MapSize;
31
+ // / Offset of the active mapped region.
32
+ size_t MapOffset;
33
+ // / Original flags for the mapped region
34
+ ur_map_flags_t MapFlags;
35
+ // / Allocated host memory used exclusively for this map.
36
+ std::shared_ptr<unsigned char []> MapMem;
37
+
38
+ BufferMap (size_t MapSize, size_t MapOffset, ur_map_flags_t MapFlags)
39
+ : MapSize(MapSize), MapOffset(MapOffset), MapFlags(MapFlags),
40
+ MapMem (nullptr ) {}
41
+
42
+ BufferMap (size_t MapSize, size_t MapOffset, ur_map_flags_t MapFlags,
43
+ std::unique_ptr<unsigned char []> &&MapMem)
44
+ : MapSize(MapSize), MapOffset(MapOffset), MapFlags(MapFlags),
45
+ MapMem(std::move(MapMem)) {}
46
+
47
+ size_t getMapSize () const noexcept { return MapSize; }
48
+
49
+ size_t getMapOffset () const noexcept { return MapOffset; }
50
+
51
+ ur_map_flags_t getMapFlags () const noexcept { return MapFlags; }
52
+ };
53
+
54
+ /* * AllocMode
55
+ * Classic: Just a normal buffer allocated on the device via hip malloc
56
+ * UseHostPtr: Use an address on the host for the device
57
+ * CopyIn: The data for the device comes from the host but the host
58
+ pointer is not available later for re-use
59
+ * AllocHostPtr: Uses pinned-memory allocation
60
+ */
61
+ enum class AllocMode { Classic, UseHostPtr, CopyIn, AllocHostPtr };
62
+
25
63
using native_type = hipDeviceptr_t;
26
64
27
65
// If this allocation is a sub-buffer (i.e., a view on an existing
28
66
// allocation), this is the pointer to the parent handler structure
29
67
ur_mem_handle_t Parent = nullptr ;
30
68
// Outer mem holding this struct in variant
31
69
ur_mem_handle_t OuterMemStruct;
32
-
33
70
// / Pointer associated with this device on the host
34
71
void *HostPtr;
35
72
// / Size of the allocation in bytes
36
73
size_t Size;
37
- // / Size of the active mapped region.
38
- size_t MapSize;
39
- // / Offset of the active mapped region.
40
- size_t MapOffset;
41
- // / Pointer to the active mapped region, if any
42
- void *MapPtr;
43
- // / Original flags for the mapped region
44
- ur_map_flags_t MapFlags;
74
+ // / A map that contains all the active mappings for this buffer.
75
+ std::unordered_map<void *, BufferMap> PtrToBufferMap;
45
76
46
- /* * AllocMode
47
- * Classic: Just a normal buffer allocated on the device via hip malloc
48
- * UseHostPtr: Use an address on the host for the device
49
- * CopyIn: The data for the device comes from the host but the host
50
- pointer is not available later for re-use
51
- * AllocHostPtr: Uses pinned-memory allocation
52
- */
53
- enum class AllocMode {
54
- Classic,
55
- UseHostPtr,
56
- CopyIn,
57
- AllocHostPtr
58
- } MemAllocMode;
77
+ AllocMode MemAllocMode;
59
78
60
79
private:
61
80
// Vector of HIP pointers
@@ -65,10 +84,8 @@ struct BufferMem {
65
84
BufferMem (ur_context_handle_t Context, ur_mem_handle_t OuterMemStruct,
66
85
AllocMode Mode, void *HostPtr, size_t Size)
67
86
: OuterMemStruct{OuterMemStruct}, HostPtr{HostPtr}, Size{Size},
68
- MapSize{0 }, MapOffset{0 }, MapPtr{nullptr }, MapFlags{UR_MAP_FLAG_WRITE},
69
- MemAllocMode{Mode}, Ptrs(Context->Devices.size(), native_type{0 }){};
70
-
71
- BufferMem (const BufferMem &Buffer) = default ;
87
+ PtrToBufferMap{}, MemAllocMode{Mode},
88
+ Ptrs (Context->Devices.size(), native_type{0 }){};
72
89
73
90
// This will allocate memory on device if there isn't already an active
74
91
// allocation on the device
@@ -98,45 +115,41 @@ struct BufferMem {
98
115
99
116
size_t getSize () const noexcept { return Size; }
100
117
101
- void *getMapPtr () const noexcept { return MapPtr; }
102
-
103
- size_t getMapSize () const noexcept { return MapSize; }
104
-
105
- size_t getMapOffset () const noexcept { return MapOffset; }
118
+ BufferMap *getMapDetails (void *Map) {
119
+ auto details = PtrToBufferMap.find (Map);
120
+ if (details != PtrToBufferMap.end ()) {
121
+ return &details->second ;
122
+ }
123
+ return nullptr ;
124
+ }
106
125
107
126
// / Returns a pointer to data visible on the host that contains
108
127
// / the data on the device associated with this allocation.
109
128
// / The offset is used to index into the HIP allocation.
110
129
// /
111
- void *mapToPtr (size_t Size, size_t Offset, ur_map_flags_t Flags) noexcept {
112
- assert (MapPtr == nullptr );
113
- MapSize = Size;
114
- MapOffset = Offset;
115
- MapFlags = Flags;
116
- if (HostPtr) {
117
- MapPtr = static_cast <char *>(HostPtr) + Offset;
130
+ void *mapToPtr (size_t MapSize, size_t MapOffset,
131
+ ur_map_flags_t MapFlags) noexcept {
132
+ void *MapPtr = nullptr ;
133
+ if (HostPtr == nullptr ) {
134
+ // / If HostPtr is invalid, we need to create a Mapping that owns its own
135
+ // / memory on the host.
136
+ auto MapMem = std::make_unique<unsigned char []>(MapSize);
137
+ MapPtr = MapMem.get ();
138
+ PtrToBufferMap.insert (
139
+ {MapPtr, BufferMap (MapSize, MapOffset, MapFlags, std::move (MapMem))});
118
140
} else {
119
- // TODO: Allocate only what is needed based on the offset
120
- MapPtr = static_cast <void *>(malloc (this ->getSize ()));
141
+ // / However, if HostPtr already has valid memory (e.g. pinned allocation),
142
+ // / we can just use that memory for the mapping.
143
+ MapPtr = static_cast <char *>(HostPtr) + MapOffset;
144
+ PtrToBufferMap.insert ({MapPtr, BufferMap (MapSize, MapOffset, MapFlags)});
121
145
}
122
146
return MapPtr;
123
147
}
124
148
125
149
// / Detach the allocation from the host memory.
126
- void unmap (void *) noexcept {
150
+ void unmap (void *MapPtr ) noexcept {
127
151
assert (MapPtr != nullptr );
128
-
129
- if (MapPtr != HostPtr) {
130
- free (MapPtr);
131
- }
132
- MapPtr = nullptr ;
133
- MapSize = 0 ;
134
- MapOffset = 0 ;
135
- }
136
-
137
- ur_map_flags_t getMapFlags () const noexcept {
138
- assert (MapPtr != nullptr );
139
- return MapFlags;
152
+ PtrToBufferMap.erase (MapPtr);
140
153
}
141
154
142
155
ur_result_t clear () {
@@ -414,7 +427,7 @@ struct ur_mem_handle_t_ {
414
427
HaveMigratedToDeviceSinceLastWrite (Context->Devices.size(), false ),
415
428
Mem{std::in_place_type<BufferMem>, Ctxt, this , Mode, HostPtr, Size} {
416
429
urContextRetain (Context);
417
- };
430
+ }
418
431
419
432
// Subbuffer constructor
420
433
ur_mem_handle_t_ (ur_mem Parent, size_t SubBufferOffset)
@@ -435,7 +448,7 @@ struct ur_mem_handle_t_ {
435
448
}
436
449
}
437
450
urMemRetain (Parent);
438
- };
451
+ }
439
452
440
453
// / Constructs the UR mem handler for an Image object
441
454
ur_mem_handle_t_ (ur_context Ctxt, ur_mem_flags_t MemFlags,
0 commit comments