-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[openmp] Fixed Support for VA for record-replay. #70396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,40 +49,87 @@ struct RecordReplayTy { | |
void *MemoryStart; | ||
void *MemoryPtr; | ||
size_t MemorySize; | ||
size_t TotalSize; | ||
GenericDeviceTy *Device; | ||
std::mutex AllocationLock; | ||
|
||
RRStatusTy Status; | ||
bool ReplaySaveOutput; | ||
uint64_t DeviceMemorySize; | ||
|
||
// Record/replay pre-allocates the largest possible device memory using the | ||
// default kind. | ||
// TODO: Expand allocation to include other kinds (device, host, shared) and | ||
// possibly use a MemoryManager to track (de-)allocations for | ||
// storing/retrieving when recording/replaying. | ||
Error preallocateDeviceMemory(uint64_t DeviceMemorySize) { | ||
// Pre-allocate memory on device. Starts with 64GB and subtracts in steps | ||
// of 1GB until allocation succeeds. | ||
const size_t MAX_MEMORY_ALLOCATION = DeviceMemorySize; | ||
|
||
void *suggestAddress(uint64_t MaxMemoryAllocation) { | ||
// Get a valid pointer address for this system | ||
void *Addr = | ||
Device->allocate(1024, /* HstPtr */ nullptr, TARGET_ALLOC_DEFAULT); | ||
Device->free(Addr); | ||
// Align Address to MaxMemoryAllocation | ||
Addr = (void *)alignPtr((Addr), MaxMemoryAllocation); | ||
return Addr; | ||
} | ||
|
||
Error preAllocateVAMemory(uint64_t MaxMemoryAllocation, void *VAddr) { | ||
size_t ASize = MaxMemoryAllocation; | ||
|
||
if (!VAddr && isRecording()) | ||
VAddr = suggestAddress(MaxMemoryAllocation); | ||
|
||
DP("Request %ld bytes allocated at %p\n", MaxMemoryAllocation, VAddr); | ||
|
||
if (auto Err = Device->memoryVAMap(&MemoryStart, VAddr, &ASize)) | ||
return Err; | ||
|
||
if (isReplaying() && VAddr != MemoryStart) { | ||
return Plugin::error("Record-Replay cannot assign the" | ||
"requested recorded address (%p, %p)", | ||
VAddr, MemoryStart); | ||
} | ||
|
||
INFO(OMP_INFOTYPE_PLUGIN_KERNEL, Device->getDeviceId(), | ||
"Allocated %" PRIu64 " bytes at %p for replay.\n", ASize, MemoryStart); | ||
|
||
MemoryPtr = MemoryStart; | ||
MemorySize = 0; | ||
TotalSize = ASize; | ||
return Plugin::success(); | ||
} | ||
|
||
Error preAllocateHeuristic(uint64_t MaxMemoryAllocation, void *VAddr) { | ||
const size_t MAX_MEMORY_ALLOCATION = MaxMemoryAllocation; | ||
constexpr size_t STEP = 1024 * 1024 * 1024ULL; | ||
MemoryStart = nullptr; | ||
for (size_t Try = MAX_MEMORY_ALLOCATION; Try > 0; Try -= STEP) { | ||
MemoryStart = | ||
Device->allocate(Try, /* HstPtr */ nullptr, TARGET_ALLOC_DEFAULT); | ||
for (TotalSize = MAX_MEMORY_ALLOCATION; TotalSize > 0; TotalSize -= STEP) { | ||
MemoryStart = Device->allocate(TotalSize, /* HstPtr */ nullptr, | ||
TARGET_ALLOC_DEFAULT); | ||
if (MemoryStart) | ||
break; | ||
} | ||
|
||
INFO(OMP_INFOTYPE_PLUGIN_KERNEL, Device->getDeviceId(), | ||
"Allocated %" PRIu64 " bytes at %p for replay.\n", TotalSize, | ||
MemoryStart); | ||
|
||
if (!MemoryStart) | ||
return Plugin::error("Allocating record/replay memory"); | ||
|
||
if (VAddr && VAddr != MemoryStart) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You could check if VAddr is within the allocation and we have enough space, in that case we succeeded, effectively. |
||
return Plugin::error("Cannot allocate recorded address"); | ||
|
||
MemoryPtr = MemoryStart; | ||
MemorySize = 0; | ||
|
||
return Plugin::success(); | ||
} | ||
|
||
Error preallocateDeviceMemory(uint64_t DeviceMemorySize, void *ReqVAddr) { | ||
if (Device->supportVAManagement()) | ||
return preAllocateVAMemory(DeviceMemorySize, ReqVAddr); | ||
|
||
uint64_t DevMemSize; | ||
if (Device->getDeviceMemorySize(DevMemSize)) | ||
return Plugin::error("Cannot determine Device Memory Size"); | ||
|
||
return preAllocateHeuristic(DevMemSize, ReqVAddr); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We ignore |
||
} | ||
|
||
void dumpDeviceMemory(StringRef Filename) { | ||
ErrorOr<std::unique_ptr<WritableMemoryBuffer>> DeviceMemoryMB = | ||
WritableMemoryBuffer::getNewUninitMemBuffer(MemorySize); | ||
|
@@ -114,8 +161,7 @@ struct RecordReplayTy { | |
bool isSaveOutputEnabled() const { return ReplaySaveOutput; } | ||
|
||
RecordReplayTy() | ||
: Status(RRStatusTy::RRDeactivated), ReplaySaveOutput(false), | ||
DeviceMemorySize(-1) {} | ||
: Status(RRStatusTy::RRDeactivated), ReplaySaveOutput(false) {} | ||
|
||
void saveImage(const char *Name, const DeviceImageTy &Image) { | ||
SmallString<128> ImageName = {Name, ".image"}; | ||
|
@@ -197,6 +243,7 @@ struct RecordReplayTy { | |
JsonKernelInfo["LoopTripCount"] = LoopTripCount; | ||
JsonKernelInfo["DeviceMemorySize"] = MemorySize; | ||
JsonKernelInfo["DeviceId"] = Device->getDeviceId(); | ||
JsonKernelInfo["BumpAllocVAStart"] = (intptr_t)MemoryStart; | ||
|
||
json::Array JsonArgPtrs; | ||
for (int I = 0; I < NumArgs; ++I) | ||
|
@@ -244,27 +291,33 @@ struct RecordReplayTy { | |
return Alloc; | ||
} | ||
|
||
Error init(GenericDeviceTy *Device, uint64_t MemSize, RRStatusTy Status, | ||
bool SaveOutput) { | ||
Error init(GenericDeviceTy *Device, uint64_t MemSize, void *VAddr, | ||
RRStatusTy Status, bool SaveOutput) { | ||
this->Device = Device; | ||
this->Status = Status; | ||
this->DeviceMemorySize = MemSize; | ||
this->ReplaySaveOutput = SaveOutput; | ||
|
||
if (auto Err = preallocateDeviceMemory(MemSize)) | ||
if (auto Err = preallocateDeviceMemory(MemSize, VAddr)) | ||
return Err; | ||
|
||
INFO(OMP_INFOTYPE_PLUGIN_KERNEL, Device->getDeviceId(), | ||
"Record Replay Initialized (%p)" | ||
" as starting address, %lu Memory Size" | ||
" and set on status %s\n", | ||
MemoryStart, MemSize, | ||
MemoryStart, TotalSize, | ||
Status == RRStatusTy::RRRecording ? "Recording" : "Replaying"); | ||
|
||
return Plugin::success(); | ||
} | ||
|
||
void deinit() { Device->free(MemoryStart); } | ||
void deinit() { | ||
if (Device->supportVAManagement()) { | ||
if (auto Err = Device->memoryVAUnMap(MemoryStart, TotalSize)) | ||
report_fatal_error("Error on releasing virtual memory space"); | ||
} else { | ||
Device->free(MemoryStart); | ||
} | ||
} | ||
|
||
} RecordReplay; | ||
|
||
|
@@ -1204,6 +1257,19 @@ Error GenericDeviceTy::queryAsync(__tgt_async_info *AsyncInfo) { | |
return queryAsyncImpl(*AsyncInfo); | ||
} | ||
|
||
Error GenericDeviceTy::memoryVAMap(void **Addr, void *VAddr, size_t *RSize) { | ||
return Plugin::error("Device does not suppport VA Management"); | ||
} | ||
|
||
Error GenericDeviceTy::memoryVAUnMap(void *VAddr, size_t Size) { | ||
return Plugin::error("Device does not suppport VA Management"); | ||
} | ||
|
||
Error GenericDeviceTy::getDeviceMemorySize(uint64_t &DSize) { | ||
return Plugin::error( | ||
"Mising getDeviceMemorySize impelmentation (required by RR-heuristic"); | ||
} | ||
|
||
Expected<void *> GenericDeviceTy::dataAlloc(int64_t Size, void *HostPtr, | ||
TargetAllocTy Kind) { | ||
void *Alloc = nullptr; | ||
|
@@ -1572,16 +1638,17 @@ int32_t __tgt_rtl_is_data_exchangable(int32_t SrcDeviceId, | |
return Plugin::get().isDataExchangable(SrcDeviceId, DstDeviceId); | ||
} | ||
|
||
int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, | ||
uint64_t MemorySize, bool isRecord, | ||
int32_t __tgt_rtl_initialize_record_replay(int32_t DeviceId, int64_t MemorySize, | ||
void *VAddr, bool isRecord, | ||
bool SaveOutput) { | ||
GenericPluginTy &Plugin = Plugin::get(); | ||
GenericDeviceTy &Device = Plugin.getDevice(DeviceId); | ||
RecordReplayTy::RRStatusTy Status = | ||
isRecord ? RecordReplayTy::RRStatusTy::RRRecording | ||
: RecordReplayTy::RRStatusTy::RRReplaying; | ||
|
||
if (auto Err = RecordReplay.init(&Device, MemorySize, Status, SaveOutput)) { | ||
if (auto Err = | ||
RecordReplay.init(&Device, MemorySize, VAddr, Status, SaveOutput)) { | ||
REPORT("WARNING RR did not intialize RR-properly with %lu bytes" | ||
"(Error: %s)\n", | ||
MemorySize, toString(std::move(Err)).data()); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not about this patch, but we really need to add documentation here, MemorySize doesn't really imply what this variable tracks. Probably renaming and docs is adequate.