Skip to content

Commit aada6d7

Browse files
authored
Arm backend: Persistently map IO memory (#20444)
Previously, each inference copied inputs and outputs like: vkMapMemory() -> memcpy() -> vkUnmapMemory() Now IO memory is mapped once and then re-used and then unmapped. cc @digantdesai @freddan80 @per @zingo @oscarandersson8218 @mansnils @Sebastian-Larsson @robell @rascani --------- Signed-off-by: Elena Zhelezina <elena.zhelezina@arm.com>
1 parent 65bc0ca commit aada6d7

2 files changed

Lines changed: 99 additions & 7 deletions

File tree

backends/arm/runtime/VGFSetup.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,73 @@ static bool find_memory_index(
778778
memory_type_out);
779779
}
780780

781+
bool VgfRepr::map_persistent_io_memory() {
782+
unmap_persistent_io_memory();
783+
784+
for (auto& io : IOs) {
785+
if (io.memory == VK_NULL_HANDLE) {
786+
ET_LOG(Error, "Cannot persistently map null Vulkan IO memory");
787+
unmap_persistent_io_memory();
788+
return false;
789+
}
790+
791+
void* persistent_memory = nullptr;
792+
793+
// IO resources may alias the same VkDeviceMemory. Vulkan memory must not be
794+
// mapped more than once at the same time, so map each unique memory once
795+
// and share the returned pointer across aliased IO entries.
796+
// Make sure that memory is HOST_VISIBLE and HOST_COHERENT.
797+
bool found_existing_mapping = false;
798+
auto mapped_memory_it = std::find_if(
799+
persistent_mapped_memories.begin(),
800+
persistent_mapped_memories.end(),
801+
[&](const auto& mapped_memory) {
802+
return mapped_memory.memory == io.memory;
803+
});
804+
805+
if (mapped_memory_it != persistent_mapped_memories.end()) {
806+
persistent_memory = mapped_memory_it->data;
807+
found_existing_mapping = true;
808+
}
809+
810+
if (!found_existing_mapping) {
811+
VkResult result = vkMapMemory(
812+
vk_device, io.memory, 0, VK_WHOLE_SIZE, 0, &persistent_memory);
813+
if (result != VK_SUCCESS) {
814+
ET_LOG(
815+
Error,
816+
"Failed to persistently map Vulkan IO memory, error %d",
817+
result);
818+
unmap_persistent_io_memory();
819+
return false;
820+
}
821+
822+
persistent_mapped_memories.push_back(PersistentMappedMemory{
823+
.memory = io.memory,
824+
.data = persistent_memory,
825+
});
826+
}
827+
828+
io.persistent_memory = persistent_memory;
829+
}
830+
831+
return true;
832+
}
833+
834+
void VgfRepr::unmap_persistent_io_memory() {
835+
for (const auto& mapped_memory : persistent_mapped_memories) {
836+
if (mapped_memory.memory != VK_NULL_HANDLE &&
837+
mapped_memory.data != nullptr) {
838+
vkUnmapMemory(vk_device, mapped_memory.memory);
839+
}
840+
}
841+
persistent_mapped_memories.clear();
842+
843+
for (auto& io : IOs) {
844+
io.persistent_memory = nullptr;
845+
}
846+
}
847+
781848
VkResult allocate_memory(
782849
VkPhysicalDevice physical,
783850
VkDevice device,
@@ -1839,6 +1906,7 @@ bool VgfRepr::process_vgf(
18391906
VK_NULL_HANDLE,
18401907
tensor_memory,
18411908
{0, 0, 0},
1909+
nullptr,
18421910
owns_memory,
18431911
true,
18441912
is_in});
@@ -1931,6 +1999,7 @@ bool VgfRepr::process_vgf(
19311999
VK_NULL_HANDLE,
19322000
buffer_memory,
19332001
{0, 0, 0},
2002+
nullptr,
19342003
owns_memory,
19352004
true,
19362005
is_in});
@@ -2117,6 +2186,7 @@ bool VgfRepr::process_vgf(
21172186
image_memory,
21182187
staging_memory,
21192188
image_extent,
2189+
nullptr,
21202190
true,
21212191
owns_image_memory,
21222192
is_in});
@@ -3433,6 +3503,15 @@ bool VgfRepr::process_vgf(
34333503
vkEndCommandBuffer(vk_execute_cmd);
34343504
}
34353505

3506+
{
3507+
VGF_PROFILE_SCOPE(event_tracer, "VGF_INIT_MAP_IO_MEMORY");
3508+
3509+
if (!map_persistent_io_memory()) {
3510+
ET_LOG(Error, "Failed to persistently map VGF IO memory");
3511+
return false;
3512+
}
3513+
}
3514+
34363515
return true;
34373516
}
34383517

@@ -3493,6 +3572,8 @@ bool VgfRepr::execute_vgf(executorch::runtime::EventTracer* event_tracer) {
34933572
}
34943573

34953574
void VgfRepr::free_vgf() {
3575+
unmap_persistent_io_memory();
3576+
34963577
if (vk_timestamp_query_pool != VK_NULL_HANDLE) {
34973578
vkDestroyQueryPool(vk_device, vk_timestamp_query_pool, nullptr);
34983579
vk_timestamp_query_pool = VK_NULL_HANDLE;

backends/arm/runtime/VGFSetup.h

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,17 @@ typedef struct IO {
4545
VkDeviceMemory image_memory;
4646
VkDeviceMemory memory;
4747
VkExtent3D image_extent;
48+
void* persistent_memory = nullptr;
4849
bool owns_memory = true;
4950
bool owns_image_memory = true;
5051
bool is_input;
5152
} IO;
5253

54+
typedef struct PersistentMappedMemory {
55+
VkDeviceMemory memory = VK_NULL_HANDLE;
56+
void* data = nullptr;
57+
} PersistentMappedMemory;
58+
5359
typedef struct SegmentState {
5460
int segment_id = -1;
5561
bool use_data_graph_pipeline = true;
@@ -128,18 +134,19 @@ class VgfRepr {
128134
std::vector<SegmentState> segments;
129135
std::vector<ResourceAlloc> extra_allocs;
130136

131-
bool map_io(IO* io, void** handle) {
132-
VkResult result =
133-
vkMapMemory(vk_device, io->memory, 0, VK_WHOLE_SIZE, 0, handle);
134-
if (result != VK_SUCCESS) {
135-
ET_LOG(Error, "Failed to map Vulkan IO memory");
137+
// Mapping to persistent IO memory
138+
static bool map_io(IO* io, void** handle) {
139+
if (io->persistent_memory == nullptr) {
140+
ET_LOG(Error, "Vulkan IO memory is not persistently mapped");
136141
return false;
137142
}
143+
*handle = io->persistent_memory;
138144
return true;
139145
}
140146

141-
void unmap_io(IO* io) {
142-
vkUnmapMemory(vk_device, io->memory);
147+
// Unmapping to persistent IO memory
148+
static void unmap_io(IO* io) {
149+
(void)io;
143150
}
144151

145152
~VgfRepr() {
@@ -168,6 +175,10 @@ class VgfRepr {
168175

169176
bool init_timestamp_queries();
170177
void read_timestamp_queries(executorch::runtime::EventTracer* event_tracer);
178+
179+
std::vector<PersistentMappedMemory> persistent_mapped_memories;
180+
bool map_persistent_io_memory();
181+
void unmap_persistent_io_memory();
171182
};
172183

173184
} // namespace vgf

0 commit comments

Comments
 (0)