0 Daumen
32 Aufrufe

Ich bin auf ein CUDA-Speicherproblem gestoßen. Dies geschieht beim Ableiten eines PyTorch-Modells. Die Eingabedaten haben eine feste Größe ([128, 1, 512]).

Wenn ich nur eine Vorhersage für eine Datei mache, schlägt die Schlussfolgerung fehl. Ich bekomme diese Werte zurück:

  pData.size(): torch.Size([128, 1, 512])
  torch.cuda.memory_allocated(): 357376
  torch.cuda.memory_reserved(): 2097152



Und in dem Fall, dass ich einen Dateiordner vorhersage, ist die Schlussfolgerung erfolgreich. Ich bekomme diese Werte:


  pData.size(): torch.Size([128, 1, 512])
  torch.cuda.memory_allocated(): 358400
  torch.cuda.memory_reserved(): 44040192



Dies ist der Fehler, den ich erhalte, wenn ich eine einzelne Vorhersage für eine Datei mache:

  ...
  x.size: torch.Size([128, 1, 512])
  x.size: torch.Size([128, 1, 512])
  x: tensor([[[0.54997, 0.52163, 0.19563, ..., 0.34677, 0.23625, 0.21865]],
  ...
  RuntimeError: CUDA out of memory. Tried to allocate 20.00 MiB (GPU 0; 7.78 GiB total capacity; 10.22 MiB already allocated; 1.19 MiB free; 22.00 MiB reserved in total by PyTorch)



Und hier ist die Ausgabe, wenn ich alle Dateien in einem Ordner durchsuche:

  ...
  x.size: torch.Size([128, 1, 512])
  x.size: torch.Size([128, 1, 512])
  x: tensor([[[0.4228, 0.4436, 0.3818, ..., 0.1387, 0.1879, 0.1545]],
  ...
  Y_pred.shape: (4986,) Y.shape: (4986,)



Der zur Vorhersage aller Dateien in einem Ordner verwendete Code lautet:

  model = UC_Model(pModel_filepath="/mnt/confiance/common/UC_Data_Folder/UC_Anomaly_Detection/models/trained_perceiver/best_model_spectra")
  (X, Y, X_val, Y_val), (l_data_X, l_data_Y) = model.prepareData(
      pDataPath="/mnt/confiance/common/UC_Data_Folder/UC_Anomaly_Detection/Dataset/test_bench_data/")
  X = np.transpose(X, (0, 2, 1))
  X_val = np.transpose(X, (0, 2, 1))
  print("X.shape: ", X.shape)
  print("Y.shape: ", Y.shape)
  X_LENGTH = len(X)
  with torch.no_grad():
      correct = 0
      total = 0
      loss = 0
      Y_pred = np.zeros(np.shape(Y))
      for i in range(X_LENGTH // BATCH_SIZE):
          x = torch.from_numpy(
              X[i * BATCH_SIZE:(i + 1) * BATCH_SIZE]
          ).float().to(DEVICE)
          print("x.size: ", x.size())
          print("x.size: ", x.size())
          y = torch.from_numpy(
              Y[i * BATCH_SIZE:(i + 1) * BATCH_SIZE]
          ).long().to(DEVICE)
          x = x.to(DEVICE)
          y_ = model(x)
          y_ = y_.cpu().argmax(dim=-1)
          total += len(y_)
          print("y_.size: ", y_.size(), " y.size(): ", y.size())
          correct += (y_ == y.cpu()).sum().item()
          Y_pred[i * BATCH_SIZE:(i + 1) * BATCH_SIZE] = y_
  plot_confusion_matrix(Y, Y_pred, anomaly_list)
  print("Y_pred.shape: ", Y_pred.shape, "Y.shape: ", Y.shape)



Und der Code zum Verarbeiten einer einzelnen Datei lautet:

 def UC_computeInference(pAiModel,pDictParams):
      pNbData=pDictParams['nbData']
      pClasses=pDictParams['classes']
      pDataPathList=pDictParams['dataPathList']
      pDataProd=pDictParams['dataProd']
      pRepertProd=pDictParams['repertProd']
      pSauvegarde=pDictParams['backup']=="oui"
      pListObjets=pDictParams['objets']
      pDataList=pDictParams['dataList']
      listInferError=[]
      x_test=[]
      y_pred=[]
      for i in range(pNbData):
          dataPreprocessed=pAiModel.prepareData(pDataPathList[i])
          prediction=pAiModel(dataPreprocessed)




In allen Fällen ist dies die Funktion, die zum Initialisieren und Aufrufen des Modells verwendet wird:

  class UC_Model:
      #-------------------------------------------------------------------------------
      ## Fonction d'initialisation du modèle
      # @param pModel_filepath : chemin d'accès du modèle fourni
      # def __init__(self, pModelpath, pModel_filepath, pParams_filepath="perceiver_params.json"):
      def __init__(self, pModel_filepath):
 
          self.name="UC_Anomaly_Detection"  # le nom du sous-répertoire du use case dans le répertoire des Use Case MODEL_BASE
          self.resPredictionsCibles=[]
          self.resPredictionsSamples=[]
          self.inferenceCible=True
 
          # Initialize model
          # self.model = create_perceiver_model()
 
          # Load model
          # /mnt/confiance/common/UC_Data_Folder/UC_Anomaly_Detection/models/trained_perceiver/best_model_spectra
          self.model = torch.load(pModel_filepath)
 
      def to_tensor(self, X, Y, i):
          x = torch.from_numpy(
              X[i * BATCH_SIZE:(i + 1) * BATCH_SIZE]
          ).float().to(DEVICE)
          print("x.size: ", x.size()) # x.size: torch.Size([128, 512, 1]) alors qu'il faut x.size: torch.Size([128, 1, 512])
          x = x.permute(0, 2, 1) # C'est pas grave, on permute
          print("after permutting: ")
          print("x.size: ", x.size())
          y = torch.from_numpy(
              Y[i * BATCH_SIZE:(i + 1) * BATCH_SIZE]
          ).long().to(DEVICE)
          x = x.to(DEVICE)
         
          return x, y
 
      ## Fonction d'appel du modèle
      # @param pData : données/samples à traiter
      # @return resultat d'inférence
      def __call__(self, pData):
          print("pData.size(): ", pData.size())
          print("torch.cuda.memory_allocated(): ", torch.cuda.memory_allocated())
          print("torch.cuda.memory_reserved(): ", torch.cuda.memory_reserved())
          # Run the Perceiver on the model
          z = self.model.perceiver(pData)
     
          # Pass through linear layers
          z = self.model.linear1(z)
          z = z.mean(dim=0)
          z = self.model.linear2(z)
          return F.log_softmax(z, dim=-1)
Avatar von

1 Antwort

0 Daumen

Antwort mit KI erzeugt:

Unterschied in CUDA-Speichernutzung zwischen Erfolg/Misserfolg Inferenz eines PyTorch-Modells mit festen Daten

Das beschriebene Szenario zeigt einen interessanten Fall, bei dem die Inferenz eines PyTorch-Modells zu unterschiedlichen CUDA-Speichernutzungsstatistiken führt, abhängig davon, ob die Vorhersage für eine einzelne Datei oder einen ganzen Ordner mit Dateien durchgeführt wird. Die beobachteten Unterschiede in der Speichernutzung, insbesondere die torch.cuda.memory_allocated() und torch.cuda.memory_reserved() Werte, können eine Einsicht in das Verhalten von PyTorch und CUDA unter verschiedenen Belastungen bieten.

Analyse

Zuerst betrachten wir die beleuchteten Speicherwerte für beide Szenarien:

- Einzelvorhersage Fehlerfall:
- torch.cuda.memory_allocated(): 357376 Bytes
- torch.cuda.memory_reserved(): 2097152 Bytes (2 MB)

- Ordner-Vorhersage Erfolgsfall:
- torch.cuda.memory_allocated(): 358400 Bytes
- torch.cuda.memory_reserved(): 44040192 Bytes (~42 MB)

Hauptunterschiede und mögliche Ursachen:

1. Speicherzuweisung (memory_allocated): Die Differenz im zugewiesenen Speicher ist minimal (1024 Bytes), was darauf hindeutet, dass die eigentliche Datenverarbeitung (also die Größe der Eingabedaten) in beiden Szenarien fast identisch ist. Der minimale Unterschied könnte auf kleine interne Zustandsänderungen im PyTorch-Modell oder in der CUDA-Speicherverwaltung zurückzuführen sein.

2. Reservierter Speicher (memory_reserved): Der signifikante Unterschied im reservierten Speicher zwischen dem Einzel- und dem Ordner-Vorhersagefall deutet darauf hin, dass CUDA im Ordner-Vorhersagefall mehr Speicher reserviert, möglicherweise um eine effizientere Batch-Verarbeitung zu ermöglichen. Das CUDA-Speichermanagementsystem versucht möglicherweise, die Leistung durch Reservierung größerer Speicherblöcke zu optimieren, wenn es erkennt, dass mehr Daten verarbeitet werden müssen.

3. RuntimeError: CUDA out of memory: Dieser Fehler im Einzelvorhersagefall scheint im Widerspruch zu den angegebenen Speicherstatistiken zu stehen, insbesondere wenn man bedenkt, dass eine signifikant größere Menge an Speicher für die Ordner-Vorhersage problemlos reserviert werden konnte. Der Fehler könnte jedoch durch die Tatsache erklärt werden, dass der reservierte Speicher nicht vollständig den sofort verfügbaren oder nutzbaren Speicher darstellt. CUDA könnte Schwierigkeiten haben, einen großen, zusammenhängenden Speicherblock zuzuweisen, obwohl insgesamt genügend Speicher reserviert ist. Dies kann insbesondere dann der Fall sein, wenn es viele kleine Speicherfragmente gibt.

Lösungsansätze:

- Speicherbereinigung und -management: Um sicherzustellen, dass CUDA genügend zusammenhängenden Speicher für die Operationen hat, kann es hilfreich sein, regelmäßig den CUDA-Cache zu leeren (torch.cuda.empty_cache()) und Speicherplatz explizit freizugeben, besonders nach dem Laden großer Modelle oder Datensätze.

- Batch-Größe überprüfen: Obwohl im bereitgestellten Beispiel die Batch-Größe möglicherweise konstant ist, sollte überprüft werden, ob die Verarbeitung kleinerer Batches den Speicherdruck verringern kann, ohne die Inferenzleistung erheblich zu beeinträchtigen.

- Modellarchitektur evaluieren: Die Größe und Komplexität des Modells können auch den CUDA-Speicherbedarf beeinflussen. Leichtere Modelle oder das Entfernen nicht notwendiger Operationen könnten den Speicherbedarf verringern.

Insgesamt scheint der Schlüssel zum Verstehen und Beheben dieses Problems im Management des CUDA-Speichers und in der effizienten Planung der Datenvorbereitungsschritte zu liegen. Durch Anpassen der Datenverarbeitungspipeline und der Speichermanagementstrategien kann man oft ein besseres Gleichgewicht zwischen Leistung und Speichernutzung finden.
Avatar von

Ein anderes Problem?

Stell deine Frage

Willkommen bei der Stacklounge! Stell deine Frage einfach und kostenlos

x
Made by a lovely community