// Copyright Epic Games, Inc.All Rights Reserved. #pragma once #include "LearningArray.h" #include "GenericPlatform/GenericPlatformMemory.h" #include "Misc/Guid.h" /** * Shared memory is used by Learning to efficiently share both experience * and policy data between a Python training sub-process and potentially * multiple unreal processes (which may be gathering that experience). */ namespace UE::Learning { /** * Basic struct containing a view to a shared memory region, its guid, * and a pointer to that region which is used for deallocation. */ template struct TSharedMemoryArrayView { FGuid Guid; TLearningArrayView View; FPlatformMemory::FSharedMemoryRegion* Region = nullptr; }; namespace SharedMemory { /** * Map a view of a region of shared memory. * * @param Guid Guid of the shared memory region * @param Shape Shape of the shared memory region * @param bCreate If this shared memory region should be created or if it already exists * @returns View of the shared memory region, guid, and pointer required for unmapping */ template TSharedMemoryArrayView Map(const FGuid Guid, const TLearningArrayShape& Shape, const bool bCreate = false) { const SIZE_T TotalSize = sizeof(ElementType) * (SIZE_T)Shape.Total(); if (TotalSize == 0) { return { FGuid(), TLearningArrayView(nullptr, Shape), nullptr }; } FPlatformMemory::FSharedMemoryRegion* RegionPointer = FPlatformMemory::MapNamedSharedMemoryRegion( Guid.ToString(PLATFORM_MAC ? EGuidFormats::Short : EGuidFormats::DigitsWithHyphensInBraces), bCreate, // I was getting odd issues allocating read-only memory so for now we always allocate as read-write FPlatformMemory::ESharedMemoryAccess::Read | FPlatformMemory::ESharedMemoryAccess::Write, TotalSize); if (ensureMsgf(RegionPointer != nullptr, TEXT("Unable to map shared memory."))) { return { Guid, TLearningArrayView((ElementType*)RegionPointer->GetAddress(), Shape), RegionPointer }; } return TSharedMemoryArrayView(); } /* * Unmaps the view of the region of shared memory */ template void Unmap(TSharedMemoryArrayView& Memory) { if (Memory.Region != nullptr) { ensureMsgf(FPlatformMemory::UnmapNamedSharedMemoryRegion(Memory.Region), TEXT("Failed to unmap shared memory.")); } Memory = TSharedMemoryArrayView(); } /** * Allocate a region of shared memory. * * @param Shape Shape of the shared memory region * @returns View of the shared memory region, guid, and pointer required for unmapping */ template TSharedMemoryArrayView Allocate(const TLearningArrayShape& Shape) { return Map(FGuid::NewGuid(), Shape, true); } /* * Deallocate the region of shared memory */ template void Deallocate(TSharedMemoryArrayView& Memory) { Unmap(Memory); } } }