[compiler-rt] [flang] [libcxx] [clang] [openmp] [llvm] [clang-tools-extra] [lldb] [OpenMP] Add memory diff dump for kernel record-replay (PR #70667)

via cfe-commits cfe-commits at lists.llvm.org
Sat Nov 4 12:56:20 PDT 2023


https://github.com/nmustakin updated https://github.com/llvm/llvm-project/pull/70667

>From 153c6d812939cd23bb71e53c71378117ed5b23c7 Mon Sep 17 00:00:00 2001
From: Nafis Mustakin <nmust004 at ucr.edu>
Date: Mon, 30 Oct 2023 07:50:59 -0700
Subject: [PATCH 1/5] Add memory diff dump for kernel record-replay

---
 .../PluginInterface/PluginInterface.cpp       | 65 +++++++++++++++----
 1 file changed, 54 insertions(+), 11 deletions(-)

diff --git a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
index 0243f0205dbf0e5..8469e8eaf1593cd 100644
--- a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
+++ b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
@@ -83,7 +83,7 @@ struct RecordReplayTy {
     return Plugin::success();
   }
 
-  void dumpDeviceMemory(StringRef Filename) {
+  void dumpDeviceMemory(StringRef Filename, bool saveDiff) {
     ErrorOr<std::unique_ptr<WritableMemoryBuffer>> DeviceMemoryMB =
         WritableMemoryBuffer::getNewUninitMemBuffer(MemorySize);
     if (!DeviceMemoryMB)
@@ -93,15 +93,58 @@ struct RecordReplayTy {
                                     MemoryStart, MemorySize, nullptr);
     if (Err)
       report_fatal_error("Error retrieving data for target pointer");
-
-    StringRef DeviceMemory(DeviceMemoryMB.get()->getBufferStart(), MemorySize);
-    std::error_code EC;
-    raw_fd_ostream OS(Filename, EC);
-    if (EC)
+    
+    std::error_code EC; 
+    raw_fd_ostream OS(Filename, EC); 
+    if(EC)
       report_fatal_error("Error dumping memory to file " + Filename + " :" +
                          EC.message());
-    OS << DeviceMemory;
-    OS.close();
+    
+    if (saveDiff){
+      //Get the pre-record memory filename  
+      SmallString<128> InputFilename = {Filename.split('.').first, ".memory"};
+      //read the pre-record memorydump
+      auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename); 
+      if(std::error_code EC = InputFileBuffer.getError())
+        report_fatal_error("Error reading pre-record device memory");
+      
+      StringRef InputBufferContents = (*InputFileBuffer)->getBuffer(); 
+      if(InputBufferContents.size() != MemorySize) 
+        report_fatal_error("Error: Pre-record device memory size mismatch");
+      
+      //get current memory contents
+      StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
+                                     DeviceMemoryMB.get()->getBuffer().size());
+      
+      //compare pre-record memorydump to current contents
+      size_t i = 0;
+      while(i < MemorySize){
+        //if mismatch found, create a new diff line
+        //current format - location, size, differences ...
+        if(InputBufferContents[i] != DeviceMemoryContents[i]){
+          OS << i << " "; //marks the start offset
+          SmallVector<uint8_t, 128> modified; 
+          modified.push_back(DeviceMemoryContents[i]);
+          size_t j = 1;
+          //loop until next match is found
+          while(InputBufferContents[i+j] != DeviceMemoryContents[i+j]){
+            modified.push_back(DeviceMemoryContents[i+j]);
+            j++;
+          }
+          OS << j << " "; //marks the length of the mismatching sequence
+          for(const auto &value : modified)
+            OS << value << " ";
+          OS << "\n"; 
+          i+=j+1; 
+        }
+        else i++; 
+      }
+    }
+    else {
+      StringRef DeviceMemory(DeviceMemoryMB.get()->getBufferStart(), MemorySize);
+      OS << DeviceMemory;
+    }
+    OS.close();  
   }
 
 public:
@@ -209,7 +252,7 @@ struct RecordReplayTy {
     JsonKernelInfo["ArgOffsets"] = json::Value(std::move(JsonArgOffsets));
 
     SmallString<128> MemoryFilename = {Name, ".memory"};
-    dumpDeviceMemory(MemoryFilename);
+    dumpDeviceMemory(MemoryFilename, false);
 
     SmallString<128> GlobalsFilename = {Name, ".globals"};
     dumpGlobals(GlobalsFilename, Image);
@@ -227,7 +270,7 @@ struct RecordReplayTy {
   void saveKernelOutputInfo(const char *Name) {
     SmallString<128> OutputFilename = {
         Name, (isRecording() ? ".original.output" : ".replay.output")};
-    dumpDeviceMemory(OutputFilename);
+    dumpDeviceMemory(OutputFilename, true);
   }
 
   void *alloc(uint64_t Size) {
@@ -1307,7 +1350,7 @@ Error GenericDeviceTy::launchKernel(void *EntryPtr, void **ArgPtrs,
         GenericKernel.getName(), GenericKernel.getImage(), ArgPtrs, ArgOffsets,
         KernelArgs.NumArgs, KernelArgs.NumTeams[0], KernelArgs.ThreadLimit[0],
         KernelArgs.Tripcount);
-
+	
   if (RecordReplay.isRecording())
     RecordReplay.saveImage(GenericKernel.getName(), GenericKernel.getImage());
 

>From 8daffad57074dd09287d321acd79c74a667eb65f Mon Sep 17 00:00:00 2001
From: Nafis Mustakin <nmust004 at ucr.edu>
Date: Mon, 30 Oct 2023 08:39:40 -0700
Subject: [PATCH 2/5] Fix clang-formatting issues, accept reviewed suggestions

---
 .../PluginInterface/PluginInterface.cpp       | 78 +++++++++----------
 1 file changed, 39 insertions(+), 39 deletions(-)

diff --git a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
index ae279d436646d9d..745dacbe361afd3 100644
--- a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
+++ b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
@@ -140,58 +140,58 @@ struct RecordReplayTy {
                                     MemoryStart, MemorySize, nullptr);
     if (Err)
       report_fatal_error("Error retrieving data for target pointer");
-    
-    std::error_code EC; 
-    raw_fd_ostream OS(Filename, EC); 
-    if(EC)
+
+    std::error_code EC;
+    raw_fd_ostream OS(Filename, EC);
+    if (EC)
       report_fatal_error("Error dumping memory to file " + Filename + " :" +
                          EC.message());
-    
-    if (saveDiff){
-      //Get the pre-record memory filename  
+
+    if (saveDiff) {
+      // Get the pre-record memory filename
       SmallString<128> InputFilename = {Filename.split('.').first, ".memory"};
-      //read the pre-record memorydump
-      auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename); 
-      if(std::error_code EC = InputFileBuffer.getError())
+      // read the pre-record memorydump
+      auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
+      if (std::error_code EC = InputFileBuffer.getError())
         report_fatal_error("Error reading pre-record device memory");
-      
-      StringRef InputBufferContents = (*InputFileBuffer)->getBuffer(); 
-      if(InputBufferContents.size() != MemorySize) 
+
+      StringRef InputBufferContents = (*InputFileBuffer)->getBuffer();
+      if (InputBufferContents.size() != MemorySize)
         report_fatal_error("Error: Pre-record device memory size mismatch");
-      
-      //get current memory contents
+
+      // get current memory contents
       StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
                                      DeviceMemoryMB.get()->getBuffer().size());
-      
-      //compare pre-record memorydump to current contents
+
+      // compare pre-record memorydump to current contents
       size_t i = 0;
-      while(i < MemorySize){
-        //if mismatch found, create a new diff line
-        //current format - location, size, differences ...
-        if(InputBufferContents[i] != DeviceMemoryContents[i]){
-          OS << i << " "; //marks the start offset
-          SmallVector<uint8_t, 128> modified; 
+      while (i < MemorySize) {
+        // if mismatch found, create a new diff line
+        // current format - location, size, differences ...
+        if (InputBufferContents[i] != DeviceMemoryContents[i]) {
+          OS << i << " "; // marks the start offset
+          SmallVector<uint8_t, 128> modified;
           modified.push_back(DeviceMemoryContents[i]);
           size_t j = 1;
-          //loop until next match is found
-          while(InputBufferContents[i+j] != DeviceMemoryContents[i+j]){
-            modified.push_back(DeviceMemoryContents[i+j]);
+          // loop until next match is found
+          while (InputBufferContents[i + j] != DeviceMemoryContents[i + j]) {
+            modified.push_back(DeviceMemoryContents[i + j]);
             j++;
           }
-          OS << j << " "; //marks the length of the mismatching sequence
-          for(const auto &value : modified)
+          OS << j << " "; // marks the length of the mismatching sequence
+          for (const auto &value : modified)
             OS << value << " ";
-          OS << "\n"; 
-          i+=j+1; 
-        }
-        else i++; 
+          OS << "\n";
+          i += j + 1;
+        } else
+          i++;
       }
-    }
-    else {
-      StringRef DeviceMemory(DeviceMemoryMB.get()->getBufferStart(), MemorySize);
+    } else {
+      StringRef DeviceMemory(DeviceMemoryMB.get()->getBufferStart(),
+                             MemorySize);
       OS << DeviceMemory;
     }
-    OS.close();  
+    OS.close();
   }
 
 public:
@@ -299,7 +299,7 @@ struct RecordReplayTy {
     JsonKernelInfo["ArgOffsets"] = json::Value(std::move(JsonArgOffsets));
 
     SmallString<128> MemoryFilename = {Name, ".memory"};
-    dumpDeviceMemory(MemoryFilename, false);
+    dumpDeviceMemory(MemoryFilename, /*saveDiff*/false);
 
     SmallString<128> GlobalsFilename = {Name, ".globals"};
     dumpGlobals(GlobalsFilename, Image);
@@ -317,7 +317,7 @@ struct RecordReplayTy {
   void saveKernelOutputInfo(const char *Name) {
     SmallString<128> OutputFilename = {
         Name, (isRecording() ? ".original.output" : ".replay.output")};
-    dumpDeviceMemory(OutputFilename, true);
+    dumpDeviceMemory(OutputFilename, /*saveDiff*/true);
   }
 
   void *alloc(uint64_t Size) {
@@ -1396,7 +1396,7 @@ Error GenericDeviceTy::launchKernel(void *EntryPtr, void **ArgPtrs,
         GenericKernel.getName(), GenericKernel.getImage(), ArgPtrs, ArgOffsets,
         KernelArgs.NumArgs, KernelArgs.NumTeams[0], KernelArgs.ThreadLimit[0],
         KernelArgs.Tripcount);
-	
+
   if (RecordReplay.isRecording())
     RecordReplay.saveImage(GenericKernel.getName(), GenericKernel.getImage());
 

>From 20a92632761639afd95496d2012c5cf8471d622e Mon Sep 17 00:00:00 2001
From: Nafis Mustakin <nmust004 at ucr.edu>
Date: Mon, 30 Oct 2023 10:34:32 -0700
Subject: [PATCH 3/5] Fix formatting issues

---
 .../common/PluginInterface/PluginInterface.cpp              | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
index 745dacbe361afd3..2a7f354a2d5b030 100644
--- a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
+++ b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
@@ -118,7 +118,7 @@ struct RecordReplayTy {
 
     return Plugin::success();
   }
-  
+
   Error preallocateDeviceMemory(uint64_t DeviceMemorySize, void *ReqVAddr) {
     if (Device->supportVAManagement())
       return preAllocateVAMemory(DeviceMemorySize, ReqVAddr);
@@ -299,7 +299,7 @@ struct RecordReplayTy {
     JsonKernelInfo["ArgOffsets"] = json::Value(std::move(JsonArgOffsets));
 
     SmallString<128> MemoryFilename = {Name, ".memory"};
-    dumpDeviceMemory(MemoryFilename, /*saveDiff*/false);
+    dumpDeviceMemory(MemoryFilename, /*saveDiff*/ false);
 
     SmallString<128> GlobalsFilename = {Name, ".globals"};
     dumpGlobals(GlobalsFilename, Image);
@@ -317,7 +317,7 @@ struct RecordReplayTy {
   void saveKernelOutputInfo(const char *Name) {
     SmallString<128> OutputFilename = {
         Name, (isRecording() ? ".original.output" : ".replay.output")};
-    dumpDeviceMemory(OutputFilename, /*saveDiff*/true);
+    dumpDeviceMemory(OutputFilename, /*saveDiff*/ true);
   }
 
   void *alloc(uint64_t Size) {

>From 6eb4f55c875e1ba8fc0aa0235eddd52ed074976d Mon Sep 17 00:00:00 2001
From: Nafis Mustakin <nmust004 at ucr.edu>
Date: Wed, 1 Nov 2023 12:04:11 -0700
Subject: [PATCH 4/5] Refactor memory diff code to dumpDeviceMemoryDiff

---
 .../PluginInterface/PluginInterface.cpp       | 115 +++++++++++-------
 1 file changed, 70 insertions(+), 45 deletions(-)

diff --git a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
index 2a7f354a2d5b030..120244ed44b7e8e 100644
--- a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
+++ b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
@@ -130,7 +130,7 @@ struct RecordReplayTy {
     return preAllocateHeuristic(DevMemSize, ReqVAddr);
   }
 
-  void dumpDeviceMemory(StringRef Filename, bool saveDiff) {
+  void dumpDeviceMemory(StringRef Filename) {
     ErrorOr<std::unique_ptr<WritableMemoryBuffer>> DeviceMemoryMB =
         WritableMemoryBuffer::getNewUninitMemBuffer(MemorySize);
     if (!DeviceMemoryMB)
@@ -141,55 +141,80 @@ struct RecordReplayTy {
     if (Err)
       report_fatal_error("Error retrieving data for target pointer");
 
+    StringRef DeviceMemory(DeviceMemoryMB.get()->getBufferStart(), MemorySize);
     std::error_code EC;
     raw_fd_ostream OS(Filename, EC);
     if (EC)
       report_fatal_error("Error dumping memory to file " + Filename + " :" +
                          EC.message());
+    OS << DeviceMemory;
+    OS.close();
+  }
+
+  void dumpDeviceMemoryDiff(StringRef Filename) {
+    ErrorOr<std::unique_ptr<WritableMemoryBuffer>> DeviceMemoryMB =
+        WritableMemoryBuffer::getNewUninitMemBuffer(MemorySize);
+    if (!DeviceMemoryMB)
+      report_fatal_error("Error creating MemoryBuffer for device memory");
+
+    auto Err = Device->dataRetrieve(DeviceMemoryMB.get()->getBufferStart(),
+                                    MemoryStart, MemorySize, nullptr);
+    if (Err)
+      report_fatal_error("Error retrieving data for target pointer");
+
+    // Get the pre-record memory filename
+    SmallString<128> InputFilename = {Filename.split('.').first, ".memory"};
+
+    // Read the pre-record memorydump
+    auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
+    if (std::error_code EC = InputFileBuffer.getError())
+      report_fatal_error("Error reading pre-record device memory");
+
+    StringRef InputBufferContents = (*InputFileBuffer)->getBuffer();
+    if (InputBufferContents.size() != MemorySize)
+      report_fatal_error("Error: Pre-record device memory size mismatch");
 
-    if (saveDiff) {
-      // Get the pre-record memory filename
-      SmallString<128> InputFilename = {Filename.split('.').first, ".memory"};
-      // read the pre-record memorydump
-      auto InputFileBuffer = MemoryBuffer::getFileOrSTDIN(InputFilename);
-      if (std::error_code EC = InputFileBuffer.getError())
-        report_fatal_error("Error reading pre-record device memory");
-
-      StringRef InputBufferContents = (*InputFileBuffer)->getBuffer();
-      if (InputBufferContents.size() != MemorySize)
-        report_fatal_error("Error: Pre-record device memory size mismatch");
-
-      // get current memory contents
-      StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
-                                     DeviceMemoryMB.get()->getBuffer().size());
-
-      // compare pre-record memorydump to current contents
-      size_t i = 0;
-      while (i < MemorySize) {
-        // if mismatch found, create a new diff line
-        // current format - location, size, differences ...
-        if (InputBufferContents[i] != DeviceMemoryContents[i]) {
-          OS << i << " "; // marks the start offset
-          SmallVector<uint8_t, 128> modified;
-          modified.push_back(DeviceMemoryContents[i]);
-          size_t j = 1;
-          // loop until next match is found
-          while (InputBufferContents[i + j] != DeviceMemoryContents[i + j]) {
-            modified.push_back(DeviceMemoryContents[i + j]);
-            j++;
-          }
-          OS << j << " "; // marks the length of the mismatching sequence
-          for (const auto &value : modified)
-            OS << value << " ";
-          OS << "\n";
-          i += j + 1;
-        } else
-          i++;
+    std::error_code EC;
+    raw_fd_ostream OS(Filename, EC);
+    if (EC)
+      report_fatal_error("Error dumping memory to file " + Filename + " :" +
+                         EC.message());
+
+    // Get current memory contents
+    StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
+                                   DeviceMemoryMB.get()->getBuffer().size());
+
+    for (size_t I = 0; I < MemorySize; ++I) {
+      // If buffers are same, continue
+      if (InputBufferContents[I] == DeviceMemoryContents[I])
+        continue;
+
+      // If mismatch is found create a new diff line
+      // Current format: location, size, differences
+      OS << I << " "; // Marks the start offset
+
+      SmallVector<uint8_t, 128> Modified;
+      Modified.push_back(DeviceMemoryContents[I]);
+
+      size_t J; // Length of current diff line
+      // Loop until next match is found
+      for (J = 1; J < MemorySize - I; ++J) {
+        // If no more mismatch, break out of the loop
+        if (InputBufferContents[I + J] == DeviceMemoryContents[I + J])
+          break;
+
+        // If mismatch continues - push diff to Modified
+        Modified.push_back(DeviceMemoryContents[I + J]);
       }
-    } else {
-      StringRef DeviceMemory(DeviceMemoryMB.get()->getBufferStart(),
-                             MemorySize);
-      OS << DeviceMemory;
+
+      OS << J << " "; // Marks the length of the mismatching sequence
+      for (const auto &value : Modified)
+        OS << value << " ";
+      OS << "\n";
+
+      // Increment I by J to skip ahead to next
+      // matching sequence in the buffer
+      I += J;
     }
     OS.close();
   }
@@ -299,7 +324,7 @@ struct RecordReplayTy {
     JsonKernelInfo["ArgOffsets"] = json::Value(std::move(JsonArgOffsets));
 
     SmallString<128> MemoryFilename = {Name, ".memory"};
-    dumpDeviceMemory(MemoryFilename, /*saveDiff*/ false);
+    dumpDeviceMemory(MemoryFilename);
 
     SmallString<128> GlobalsFilename = {Name, ".globals"};
     dumpGlobals(GlobalsFilename, Image);
@@ -317,7 +342,7 @@ struct RecordReplayTy {
   void saveKernelOutputInfo(const char *Name) {
     SmallString<128> OutputFilename = {
         Name, (isRecording() ? ".original.output" : ".replay.output")};
-    dumpDeviceMemory(OutputFilename, /*saveDiff*/ true);
+    dumpDeviceMemoryDiff(OutputFilename);
   }
 
   void *alloc(uint64_t Size) {

>From 09ab2681e3687723898a3dd7cbed2b5f5ecf126d Mon Sep 17 00:00:00 2001
From: Nafis Mustakin <nmust004 at ucr.edu>
Date: Sat, 4 Nov 2023 12:50:59 -0700
Subject: [PATCH 5/5] Simplify Diff logic

---
 .../PluginInterface/PluginInterface.cpp       | 26 +++++++------------
 1 file changed, 10 insertions(+), 16 deletions(-)

diff --git a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
index 120244ed44b7e8e..22e8a6f70d03ec7 100644
--- a/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
+++ b/openmp/libomptarget/plugins-nextgen/common/PluginInterface/PluginInterface.cpp
@@ -184,37 +184,31 @@ struct RecordReplayTy {
     StringRef DeviceMemoryContents(DeviceMemoryMB.get()->getBuffer().data(),
                                    DeviceMemoryMB.get()->getBuffer().size());
 
+    // Loop over all memory locations
+    // If mismatch is found create a new diff line
+    // Diff format: location, size, differences
     for (size_t I = 0; I < MemorySize; ++I) {
       // If buffers are same, continue
       if (InputBufferContents[I] == DeviceMemoryContents[I])
         continue;
 
-      // If mismatch is found create a new diff line
-      // Current format: location, size, differences
       OS << I << " "; // Marks the start offset
 
       SmallVector<uint8_t, 128> Modified;
       Modified.push_back(DeviceMemoryContents[I]);
 
-      size_t J; // Length of current diff line
-      // Loop until next match is found
-      for (J = 1; J < MemorySize - I; ++J) {
+      for (I += 1; I < MemorySize; ++I) {
         // If no more mismatch, break out of the loop
-        if (InputBufferContents[I + J] == DeviceMemoryContents[I + J])
+        if (InputBufferContents[I] == DeviceMemoryContents[I])
           break;
-
         // If mismatch continues - push diff to Modified
-        Modified.push_back(DeviceMemoryContents[I + J]);
+        Modified.push_back(DeviceMemoryContents[I]);
       }
-
-      OS << J << " "; // Marks the length of the mismatching sequence
-      for (const auto &value : Modified)
-        OS << value << " ";
+      OS << Modified.size()
+         << " "; // Marks the length of the mismatching sequence
+      for (const auto &Value : Modified)
+        OS << Value << " ";
       OS << "\n";
-
-      // Increment I by J to skip ahead to next
-      // matching sequence in the buffer
-      I += J;
     }
     OS.close();
   }



More information about the cfe-commits mailing list