Freigeben über


Behandeln von Problemen mit ParallelRunStep

GILT FÜR:Azure Machine Learning SDK v1 für Python

Von Bedeutung

Dieser Artikel enthält Informationen zur Verwendung des Azure Machine Learning SDK v1. SDK v1 ist ab dem 31. März 2025 veraltet. Der Support für sie endet am 30. Juni 2026. Sie können SDK v1 bis zu diesem Datum installieren und verwenden. Ihre vorhandenen Workflows mit SDK v1 funktionieren weiterhin nach dem Enddatum des Supports. Sie können jedoch Sicherheitsrisiken oder Breaking Changes im Falle von Architekturänderungen im Produkt ausgesetzt sein.

Es wird empfohlen, vor dem 30. Juni 2026 zum SDK v2 zu wechseln. Weitere Informationen zu SDK v2 finden Sie unter Was ist Azure Machine Learning CLI und Python SDK v2? und die SDK v2-Referenz.

Dieser Artikel enthält eine Problembehandlungsanleitung für den Fall, dass bei der Verwendung der Klasse ParallelRunStep aus dem Azure Machine Learning SDK Fehler auftreten.

Allgemeine Tipps zur Problembehandlung für Pipelines finden Sie unter Problembehandlung bei Machine Learning-Pipelines.

Lokales Testen von Skripts

ParallelRunStep wird als Schritt in ML-Pipelines ausgeführt. Als Erstes sollten Sie ggf. Ihre Skripts lokal testen.

Anforderungen an Einstiegsskripts

Das Einstiegsskript für ParallelRunStepmuss eine run()-Funktion enthalten und kann optional eine init()-Funktion enthalten:

  • init(): Verwenden Sie diese Funktion für alle aufwendigen oder allgemeinen Vorbereitungsmaßnahmen für die spätere Verarbeitung. Ein Beispiel wäre etwa das Laden des Modells in ein globales Objekt. Diese Funktion wird nur einmal zu Beginn des Prozesses aufgerufen.

    Hinweis

    Wenn Ihre init-Methode ein Ausgabeverzeichnis erstellt, geben Sie parents=True und exist_ok=True an. Die init-Methode wird von jedem Workerprozess auf jedem Knoten aufgerufen, auf dem der Auftrag ausgeführt wird.

  • run(mini_batch): Die Funktion wird für jede mini_batch-Instanz ausgeführt.
    • mini_batch: ParallelRunStep ruft die run-Methode auf und übergibt entweder eine Liste oder einen Pandas-Datenrahmen (DataFrame) als Argument an die Methode. Jeder Eintrag in „mini_batch“ entspricht einem Dateipfad, wenn die Eingabe ein FileDataset ist, bzw. einem Pandas-Datenrahmen (DataFrame), wenn die Eingabe ein TabularDataset ist.
    • response: Die run()-Methode sollte einen Pandas-Datenrahmen (DataFrame) oder ein Array zurückgeben. Bei Verwendung von „append_row output_action“ werden diese zurückgegebenen Elemente am Ende der allgemeinen Ausgabedatei hinzugefügt. Bei Verwendung von „summary_only“ wird der Inhalt der Elemente ignoriert. Bei allen Ausgabeaktionen geben die zurückgegebenen Ausgabeelemente jeweils eine erfolgreiche Ausführung für ein Eingabeelement aus dem Eingabeminibatch an. Vergewissern Sie sich, dass das Ausführungsergebnis genügend Daten für eine Zuordnung zwischen der Ein- und der Ausgabe des Ausführungsergebnisses enthält. Die Ausführungsausgaben werden in die Ausgabedatei geschrieben. Da hierbei nicht unbedingt die Reihenfolge eingehalten wird, müssen Sie einen Schlüssel in der Ausgabe verwenden, um sie einer Eingabe zuzuordnen.

      Hinweis

      Für jedes Eingabeelement wird ein Ausgabeelement erwartet.

%%writefile digit_identification.py
# Snippets from a sample script.
# Refer to the accompanying digit_identification.py
# (https://github.com/Azure/MachineLearningNotebooks/tree/master/how-to-use-azureml/machine-learning-pipelines/parallel-run)
# for the implementation script.

import os
import numpy as np
import tensorflow as tf
from PIL import Image
from azureml.core import Model


def init():
    global g_tf_sess

    # Pull down the model from the workspace
    model_path = Model.get_model_path("mnist")

    # Construct a graph to execute
    tf.reset_default_graph()
    saver = tf.train.import_meta_graph(os.path.join(model_path, 'mnist-tf.model.meta'))
    g_tf_sess = tf.Session()
    saver.restore(g_tf_sess, os.path.join(model_path, 'mnist-tf.model'))


def run(mini_batch):
    print(f'run method start: {__file__}, run({mini_batch})')
    resultList = []
    in_tensor = g_tf_sess.graph.get_tensor_by_name("network/X:0")
    output = g_tf_sess.graph.get_tensor_by_name("network/output/MatMul:0")

    for image in mini_batch:
        # Prepare each image
        data = Image.open(image)
        np_im = np.array(data).reshape((1, 784))
        # Perform inference
        inference_result = output.eval(feed_dict={in_tensor: np_im}, session=g_tf_sess)
        # Find the best probability, and add it to the result list
        best_result = np.argmax(inference_result)
        resultList.append("{}: {}".format(os.path.basename(image), best_result))

    return resultList

Wenn das Verzeichnis mit Ihrem Rückschlussskript noch andere Dateien oder Ordner enthält, können Sie einen Verweis darauf erstellen, indem Sie das aktuelle Arbeitsverzeichnis ermitteln. Wenn Sie Ihre Pakete importieren möchten, können Sie ihren Paketordner auch an sys.path anfügen.

script_dir = os.path.realpath(os.path.join(__file__, '..',))
file_path = os.path.join(script_dir, "<file_name>")

packages_dir = os.path.join(file_path, '<your_package_folder>')
if packages_dir not in sys.path:
    sys.path.append(packages_dir)
from <your_package> import <your_class>

Parameter für ParallelRunConfig

ParallelRunConfig ist die Hauptkonfiguration für die ParallelRunStep-Instanz innerhalb der Azure Machine Learning-Pipeline. Sie dient dazu, Ihr Skript zu umschließen und die erforderlichen Parameter zu konfigurieren, einschließlich der folgenden Einträge:

  • entry_script: ein Benutzerskript als lokaler Dateipfad, das parallel auf mehreren Knoten ausgeführt werden soll. Wenn source_directory vorhanden ist, verwenden Sie einen relativen Pfad. Verwenden Sie andernfalls einen beliebigen Pfad, auf den auf dem Computer zugegriffen werden kann.

  • mini_batch_size: die Größe des Minibatches, der an einen einzelnen Aufruf von run() übergeben wird (optional; Standardwerte sind 10-Dateien für FileDataset und 1MB für TabularDataset)

    • Bei FileDataset handelt es sich um die Anzahl der Dateien (Mindestwert: 1). Sie können mehrere Dateien zu einem Minibatch zusammenfassen.
    • Bei TabularDataset handelt es sich um die Datengröße. Beispielwerte: 1024, 1024KB, 10MB und 1GB. Empfohlener Wert: 1MB. Der Minibatch auf der Grundlage von TabularDataset überschreitet nie die Dateigrenzen. Wenn Sie z. B. über unterschiedlich große CSV-Dateien verfügen, ist die kleinste Datei 100 KB und die größte Datei 10 MB groß. Wenn mini_batch_size = 1MB festgelegt wurde, werden die Dateien, die kleiner als 1 MB sind, als ein Minibatch behandelt, und die Dateien, die größer als 1 MB sind, werden auf mehrere Minibatches aufgeteilt.

      Hinweis

      TabularDatasets auf SQL-Grundlage können nicht partitioniert werden. TabularDatasets aus einer einzelnen Parquet-Datei und einer einzelnen Zeilengruppe können nicht partitioniert werden.

  • error_threshold: die Anzahl von Datensatzfehlern für TabularDataset bzw. Dateifehlern für FileDataset, die während der Verarbeitung ignoriert werden sollen. Übersteigt die Fehleranzahl für die gesamte Eingabe diesen Wert, wird der Auftrag abgebrochen. Der Fehlerschwellenwert gilt für die gesamte Eingabe und nicht für den einzelnen Minibatch, der an die run()-Methode übermittelt wird. Zulässiger Bereich: [-1, int.max]. -1 gibt an, dass bei der Verarbeitung alle Fehler ignoriert werden sollen.

  • output_action: Einer der folgenden Werte gibt an, wie die Ausgabe strukturiert werden soll:

    • summary_only: Das Benutzerskript soll die Ausgabedateien speichern. Die Ausgaben von run() werden nur für die Berechnung der Fehlerschwellenwerte verwendet.
    • append_row: ParallelRunStep erstellt für alle Eingaben eine einzelne Datei im Ausgabeordner, in der alle Ausgaben angefügt werden (jeweils auf einer Zeile).
  • append_row_file_name zum Anpassen des Namens der Ausgabedatei für „append_row output_action“ (optional; der Standardwert ist parallel_run_step.txt)

  • source_directory: Pfade zu Ordnern mit allen Dateien, die am Computeziel ausgeführt werden sollen (optional)

  • compute_target: Nur AmlCompute wird unterstützt.

  • node_count: Anzahl von Serverknoten, die zum Ausführen des Benutzerskripts verwendet werden sollen

  • process_count_per_node: Anzahl der Workerprozesse pro Knoten zum parallelen Ausführen des Einstiegsskripts. Für einen GPU-Computer lautet der Standardwert 1. Für einen CPU-Computer ist der Standardwert die Anzahl der Kerne pro Knoten. Ein Workerprozess ruft run() wiederholt auf und übergibt dabei den Minibatch, den er als Parameter empfängt. Die Gesamtanzahl der Workerprozesse in Ihrem Auftrag ist process_count_per_node * node_count. Sie legt maximale Anzahl von run() für die parallele Ausführung fest.

  • environment: Die Python-Umgebungsdefinition. Sie kann für die Verwendung einer vorhandenen Python-Umgebung oder für die Einrichtung einer temporären Umgebung konfiguriert werden. Die Definition kann auch zum Festlegen der erforderlichen Anwendungsabhängigkeiten verwendet werden (optional).

  • logging_level: Die Ausführlichkeit des Protokolls. Mögliche Werte (mit zunehmender Ausführlichkeit): WARNING, INFO und DEBUG. (optional; Standardwert: INFO)

  • run_invocation_timeout: Timeout für den Aufruf der run()-Methode in Sekunden. (optional; Standardwert: 60)

  • run_max_try: maximale Anzahl der Versuche von run() für einen Minibatch. Ein run() gilt als fehlerhaft, wenn eine Ausnahme ausgelöst wird oder beim Erreichen von run_invocation_timeout nichts zurückgegeben wird (optional; Standardwert: 3).

Sie können mini_batch_size, node_count, process_count_per_node, logging_level, run_invocation_timeout und run_max_try auf PipelineParameter festlegen, damit Sie die Parameterwerte beim erneuten Senden einer Pipelineausführung optimieren können.

Sichtbarkeit von CUDA-Geräten

Für Computeziele mit GPUs wird die Umgebungsvariable CUDA_VISIBLE_DEVICES in Workerprozessen festgelegt. In AmlCompute finden Sie die Gesamtanzahl der GPU-Geräte in der Umgebungsvariable AZ_BATCHAI_GPU_COUNT_FOUND, die automatisch festgelegt wird. Wenn jeder Workerprozess über eine dedizierte GPU verfügen soll, legen Sie process_count_per_node auf die Anzahl der GPU-Geräte auf einem Computer fest. Anschließend wird jedem Workerprozess ein eindeutiger Index in CUDA_VISIBLE_DEVICES zugewiesen. Wenn ein Workerprozess aus irgendeinem Grund beendet wird, verwendet der nächste gestartete Workerprozess den freigegebenen GPU-Index.

Wenn die Gesamtanzahl der GPU-Geräte kleiner als process_count_per_node ist, können Workerprozesse mit kleinerem Index einem GPU-Index zugewiesen werden, bis alle GPUs belegt wurden.

Wenn beispielsweise die Gesamtanzahl der GPU-Geräte 2 und process_count_per_node = 4 ist, weisen Prozess 0 und Prozess 1 den Index 0 und 1 auf. Die Prozesse 2 und 3 haben keine Umgebungsvariable. Bei einer Bibliothek, die diese Umgebungsvariable für die GPU-Zuweisung verwendet, verfügen die Prozesse 2 und 3 nicht über GPUs und versuchen nicht, GPU-Geräte zu beziehen. Der Prozess 0 gibt den GPU-Index 0 frei, wenn er beendet wird. Dem nächsten Prozess (Prozess 4) wird ggf. der GPU-Index 0 zugewiesen.

Weitere Informationen finden Sie unter CUDA Pro Tip: Control GPU Visibility with CUDA_VISIBLE_DEVICES.

Parameter zum Erstellen von ParallelRunStep

Erstellen Sie ParallelRunStep mithilfe von Skript, Umgebungskonfiguration und Parametern. Geben Sie das Computeziel an, das Sie bereits als Ausführungsziel für Ihr Rückschlussskript an Ihren Arbeitsbereich angefügt haben. Verwenden Sie ParallelRunStep, um den Pipelineschritt für den Batchrückschluss mit folgenden Parametern zu erstellen:

  • name: Name des Schritts mit den Benennungseinschränkungen: eindeutig, 3–32 Zeichen und regulärer Ausdruck ^[a-z]([-a-z0-9]*[a-z0-9])?$
  • parallel_run_config: ein ParallelRunConfig-Objekt, wie zuvor definiert
  • inputs: mindestens ein Azure Machine Learning-Dataset mit einem einzelnen Typ, das für die Parallelverarbeitung partitioniert werden soll
  • side_inputs: Verweisdaten oder Datasets, die als Seiteneingabe verwendet werden und für die keine Partitionierung erforderlich ist
  • output: ein OutputFileDatasetConfig-Objekt, das den Verzeichnispfad darstellt, in dem die Ausgabedaten gespeichert werden sollen
  • arguments: eine Liste mit Argumenten, die an das Benutzerskript übergeben werden. Verwenden Sie „unknown_args“, um sie in Ihrem Einstiegsskript zu nutzen (optional).
  • allow_reuse gibt an, ob bei dem Schritt vorherige Ergebnisse wiederverwendet werden sollen, wenn er mit den gleichen Einstellungen/Eingaben ausgeführt wird. Ist der Parameter auf False festgelegt, wird für diesen Schritt bei der Pipelineausführung immer eine neue Ausführung generiert. (optional; Standardwert: True)
from azureml.pipeline.steps import ParallelRunStep

parallelrun_step = ParallelRunStep(
    name="predict-digits-mnist",
    parallel_run_config=parallel_run_config,
    inputs=[input_mnist_ds_consumption],
    output=output_dir,
    allow_reuse=True
)

Debuggen von Skripts aus Remotekontext

Der Übergang vom lokalen Debuggen eines Bewertungsskripts zum Debuggen eines Bewertungsskripts in einer echten Pipeline kann einen schwierigen Schritt darstellen. Wie Sie Ihre Protokolle im Portal finden, erfahren Sie im Abschnitt zu Machine Learning-Pipelines über das Debuggen von Skripts aus einem Remotekontext. Die Informationen in diesem Abschnitt gelten auch für ParallelRunStep.

Aufgrund der verteilten Struktur von ParallelRunStep-Aufträgen gibt es Protokolle aus mehreren verschiedenen Quellen. Es werden jedoch zwei konsolidierte Dateien erstellt, die allgemeine Informationen enthalten:

  • ~/logs/job_progress_overview.txt: Diese Datei enthält allgemeine Informationen zur Anzahl der bisher erstellten Minibatches (auch als Aufgaben bezeichnet) und zur Anzahl der bisher verarbeiteten Minibatches. Am Ende wird das Ergebnis des Auftrags aufgeführt. Wenn bei dem Auftrag ein Fehler auftritt, wird die Fehlermeldung angezeigt, und es wird beschrieben, wo mit der Problembehandlung begonnen werden sollte.

  • ~/logs/job_result.txt zeigt das Ergebnis des Auftrags an. Wenn bei dem Auftrag ein Fehler aufgetreten ist, wird die Fehlermeldung angezeigt, und es wird beschrieben, wo mit der Problembehandlung begonnen werden sollte.

  • ~/logs/job_error.txt: In dieser Datei werden die Fehler in Ihrem Skript zusammengefasst.

  • ~/logs/sys/master_role.txt: Diese Datei stellt die Prinzipalknotenansicht (auch als Orchestrator bezeichnet) des laufenden Auftrags bereit. Dies umfasst die Aufgabenerstellung, die Fortschrittsüberwachung und das Ergebnis der Ausführung.

  • ~/logs/sys/job_report/processed_mini-batches.csv: eine Tabelle aller verarbeiteten Minibatches. Sie enthält das Ergebnis jeder Minibatchausführung, die ID des Ausführungs-Agent-Knotens und den Prozessnamen. Außerdem sind die verstrichenen Zeit und Fehlermeldungen enthalten. Die Protokolle für jede Ausführung von Minibatches finden Sie über die Knoten-ID und den Prozessnamen.

Protokolle, die mit dem EntryScript-Hilfsprogramm aus dem Einstiegsskript generiert wurden, sowie Ausgabeanweisungen finden Sie in den folgenden Dateien:

  • ~/logs/user/entry_script_log/<node_id>/<process_name>.log.txt: Diese Dateien sind die Protokolle, die von „entry_script“ mithilfe des EntryScript-Hilfsprogramms geschrieben wurden.

  • ~/logs/user/stdout/<node_id>/<process_name>.stdout.txt: Bei diesen Dateien handelt es sich um die Protokolle von stdout (z. B. eine print-Anweisung) von „entry_script“.

  • ~/logs/user/stderr/<node_id>/<process_name>.stderr.txt: Diese Dateien sind die Protokolle von stderr von „entry_script“.

Der Screenshot zeigt beispielsweise „minibatch 0 failed on node 0 process001”. Die entsprechenden Protokolle für Ihr Einstiegsskript finden Sie in ~/logs/user/entry_script_log/0/process001.log.txt, ~/logs/user/stdout/0/process001.log.txt und ~/logs/user/stderr/0/process001.log.txt.

Screenshot einer Beispieldatei „processed_mini-batches.csv”

Wenn Sie Einzelheiten dazu erhalten möchten, wie die einzelnen Knoten das Bewertungsskript ausgeführt haben, sehen Sie sich die jeweiligen Prozessprotokolle für jeden Knoten an. Sie finden die Prozessprotokolle im Ordner ~/logs/sys/node, gruppiert nach Workerknoten:

  • ~/logs/sys/node/<node_id>/<process_name>.txt: Diese Datei enthält ausführliche Informationen zu den einzelnen Minibatches, die von einem Worker abgerufen oder abgeschlossen wurden. Für jeden Minibatch enthält diese Datei Folgendes:

    • Die IP-Adresse und die PID des Workerprozesses
    • Die Gesamtzahl der Elemente, die Anzahl der erfolgreich verarbeiteten Elemente und die Anzahl der nicht erfolgreichen Elemente.
    • Die Startzeit, die Dauer, die Verarbeitungszeit und die Laufzeit der Methode

Sie können für jeden Knoten auch die Ergebnisse regelmäßiger Prüfungen der Ressourcennutzung anzeigen. Die Protokoll- und Setupdateien befinden sich in diesem Ordner:

  • ~/logs/perf: Legen Sie --resource_monitor_interval fest, um das Prüfintervall in Sekunden zu ändern. Das Standardintervall ist 600 (ungefähr 10 Minuten). Um die Überwachung zu beenden, legen Sie den Wert auf 0 fest. Jeder Ordner <node_id> enthält Folgendes:

    • os/: Informationen zu allen laufenden Prozessen auf dem Knoten. Bei einer Prüfung wird ein Betriebssystembefehl ausgeführt und das Ergebnis in einer Datei gespeichert. Unter Linux ist der Befehl ps. Unter Windows verwenden Sie tasklist.
      • %Y%m%d%H: Der Name des Unterordners ist die Uhrzeit zur vollen Stunde.
        • processes_%M: Die Datei endet mit der Minute der Prüfzeit.
    • node_disk_usage.csv: detaillierte Datenträgernutzung des Knotens
    • node_resource_usage.csv: Übersicht über den Ressourceneinsatz des Knotens
    • processes_resource_usage.csv: Übersicht über den Ressourceneinsatz der einzelnen Prozesse

Häufige Gründe für Auftragsfehler

SystemExit: 42

Exits 41 und 42 sind von PRS entworfene Ausgangscodes. Workerknoten werden mit „41“ beendet, um den Compute-Manager zu benachrichtigen, dass sie unabhängig beendet wurden. Dies wird erwartet. Ein Leaderknoten kann mit dem Wert 0 oder 42 beendet werden, der das Auftragsergebnis angibt. Exit 42 bedeutet, dass der Auftrag fehlgeschlagen ist. Den Fehlergrund finden Sie in ~/logs/job_result.txt. Sie können dem vorherigen Abschnitt folgen, um Ihren Auftrag zu debuggen.

Datenberechtigung

Der Fehler des Auftrags gibt an, dass die Berechnung nicht auf Eingabedaten zugreifen kann. Wenn identitätsbasiert für Ihren Computecluster und Speicher verwendet wird, finden Sie Informationen unter Identitätsbasierte Datenauthentifizierung.

Prozesse unerwartet beendet

Prozesse können aufgrund unerwarteter oder unbehandelter Ausnahmen abstürzen, das System beendet Prozesse aufgrund von nicht genügend Arbeitsspeicher. In den PRS-Systemprotokollen ~/logs/sys/node/<node-id>/_main.txt finden Sie Fehler wie die folgenden.

<process-name> exits with returncode -9.

Nicht genügend Arbeitsspeicher

~/logs/perf protokolliert den Ressourcenverbrauch von Prozessen. Sie finden darin die Speicherauslastung der einzelnen Aufgabenprozessoren. Sie können die Gesamtspeicherauslastung auf dem Knoten abschätzen.

Den Fehler „Nicht genügend Arbeitsspeicher” finden Sie in ~/system_logs/lifecycler/<node-id>/execution-wrapper.txt.

Es wird empfohlen, die Anzahl der Prozesse pro Knoten zu verringern oder die VM-Größe zu aktualisieren, wenn die Computeressourcen die Grenzwerte erreichen.

Nicht behandelte Ausnahmen

In einigen Fällen können die Python-Prozesse den fehlerhaften Stapel nicht abfangen. Sie können eine Umgebungsvariable env["PYTHONFAULTHANDLER"]="true" hinzufügen, um in Python integrierte Fehlerhandler zu aktivieren.

Timeout für Minibatch

Sie können das Argument run_invocation_timeout entsprechend Ihren Minibatchaufgaben anpassen. Wenn die run()-Funktionen mehr Zeit als erwartet benötigen, sind hier einige Tipps.

  • Überprüfen Sie die verstrichene Zeit und die Verarbeitungszeit des Minibatchs. Die Verarbeitungszeit misst die CPU-Zeit des Prozesses. Wenn die Verarbeitungszeit deutlich kürzer als die verstrichene Zeit ist, können Sie überprüfen, ob die Aufgaben einige umfangreiche E/A-Vorgänge oder Netzwerkanforderungen enthalten. Lange Latenz dieser Vorgänge ist ein häufiger Grund für Minibatch-Timeouts.

  • Einige bestimmte Minibatches dauern länger als andere. Sie können entweder die Konfiguration aktualisieren oder versuchen, mit Eingabedaten zu arbeiten, um die Verarbeitungszeit des Minibatch auszugleichen.

Wie protokolliere ich mein Benutzerskript aus einem Remotekontext?

ParallelRunStep kann mehrere Prozesse auf einem Knoten entsprechend dem „process_count_per_node“ ausführen. Es wird empfohlen, die ParallelRunStep-Protokollierung wie unten gezeigt zu verwenden, um die Protokolle der einzelnen Prozesse auf dem Knoten zu organisieren und die Ausgabe- und Protokollanweisungen zu kombinieren. Sie können eine Protokollierung von EntryScript abrufen, damit die Protokolle im Portal im Ordner logs/user angezeigt werden.

Beispiel für ein Einstiegsskript mit Protokollierung:

from azureml_user.parallel_run import EntryScript

def init():
    """Init once in a worker process."""
    entry_script = EntryScript()
    logger = entry_script.logger
    logger.info("This will show up in files under logs/user on the Azure portal.")


def run(mini_batch):
    """Call once for a mini batch. Accept and return the list back."""
    # This class is in singleton pattern. It returns the same instance as the one in init()
    entry_script = EntryScript()
    logger = entry_script.logger
    logger.info(f"{__file__}: {mini_batch}.")
    ...

    return mini_batch

In welche logging-Senke wird die Nachricht von Python übermittelt?

ParallelRunStep legt einen Handler für die Stammprotokollierung fest, der die Nachricht an die Senke logs/user/stdout/<node_id>/processNNN.stdout.txt übermittelt.

logging hat standardmäßig die Stufe INFO. Standardmäßig werden niedrigere Stufen als INFO nicht angezeigt, also z. B. DEBUG.

Wie kann ich in eine Datei schreiben, die im Portal angezeigt werden soll?

Dateien im Ordner /logs werden in das Portal hochgeladen und dort angezeigt. Sie können den Ordner logs/user/entry_script_log/<node_id> wie unten gezeigt abrufen und Ihren Dateipfad zum Schreiben zusammenstellen:

from pathlib import Path
from azureml_user.parallel_run import EntryScript

def init():
    """Init once in a worker process."""
    entry_script = EntryScript()
    log_dir = entry_script.log_dir
    log_dir = Path(entry_script.log_dir)  # logs/user/entry_script_log/<node_id>/.
    log_dir.mkdir(parents=True, exist_ok=True) # Create the folder if not existing.

    proc_name = entry_script.agent_name  # The process name in pattern "processNNN".
    fil_path = log_dir / f"{proc_name}_<file_name>" # Avoid conflicting among worker processes with proc_name.

Wie wird die Anmeldung neuer Prozesse gehandhabt?

Sie können mit dem subprocess-Modul neue Prozesse in Ihrem Einstiegsskript generieren, eine Verbindung mit ihren Pipes für Eingabe/Ausgabe/Fehler herstellen und die zugehörigen Rückgabecodes abrufen.

Es wird empfohlen, die run()-Funktion mit capture_output=True zu verwenden. Fehler werden in logs/user/error/<node_id>/<process_name>.txt angezeigt.

Wenn Sie Popen() verwenden möchten, sollten Sie stdout/stderr wie folgt in Dateien umleiten:

from pathlib import Path
from subprocess import Popen

from azureml_user.parallel_run import EntryScript


def init():
    """Show how to redirect stdout/stderr to files in logs/user/entry_script_log/<node_id>/."""
    entry_script = EntryScript()
    proc_name = entry_script.agent_name  # The process name in pattern "processNNN".
    log_dir = Path(entry_script.log_dir)  # logs/user/entry_script_log/<node_id>/.
    log_dir.mkdir(parents=True, exist_ok=True) # Create the folder if not existing.
    stdout_file = str(log_dir / f"{proc_name}_demo_stdout.txt")
    stderr_file = str(log_dir / f"{proc_name}_demo_stderr.txt")
    proc = Popen(
        ["...")],
        stdout=open(stdout_file, "w"),
        stderr=open(stderr_file, "w"),
        # ...
    )

Hinweis

Ein Workerprozess führt den Systemcode und den Code des Einstiegsskripts im selben Prozess aus.

Wenn stdout oder stderr nicht angegeben wurden, wird die Einstellung des Workerprozesses von Unterprozessen geerbt, die mit Popen() in Ihrem Einstiegsskript erstellt wurden.

stdout schreibt in ~/logs/sys/node/<node_id>/processNNN.stdout.txt und stderr in ~/logs/sys/node/<node_id>/processNNN.stderr.txt.

Wie kann ich eine Datei in das Ausgabeverzeichnis schreiben und dann im Portal anzeigen?

Sie können das Ausgabeverzeichnis aus der EntryScript-Klasse abrufen und darin schreiben. Zum Anzeigen der geschriebenen Dateien wählen Sie im Azure Machine Learning-Portal in der Ausführungsansicht des Schritts die Registerkarte Ausgaben und Protokolle aus. Wählen Sie den Link Datenausgaben aus, und führen Sie dann die im Dialogfeld beschriebenen Schritte aus.

Verwenden Sie EntryScript in Ihrem Einstiegsskript, wie im folgenden Beispiel gezeigt:

from pathlib import Path
from azureml_user.parallel_run import EntryScript

def run(mini_batch):
    output_dir = Path(entry_script.output_dir)
    (Path(output_dir) / res1).write...
    (Path(output_dir) / res2).write...

Wie kann ich Seiteneingaben (z. B. eine oder mehrere Dateien mit einer Nachschlagetabelle) an alle meine Worker übergeben?

Benutzende können mit dem side_inputs-Parameter von ParalleRunStep Verweisdaten an das Skript übergeben. Alle als „side_inputs“ (Seiteneingaben) bereitgestellten Datasets werden auf den einzelnen Workerknoten eingebunden. Die Benutzenden können den Speicherort der Eingabe durch Übergeben des Arguments abrufen.

Konstruieren Sie ein Dataset, das die Verweisdaten enthält, geben Sie einen lokalen Mount-Pfad an und registrieren Sie es in Ihrem Arbeitsbereich. Übergeben Sie es an den side_inputs-Parameter für Ihr ParallelRunStep. Zusätzlich können Sie den zugehörigen Pfad im Abschnitt arguments hinzufügen, um einfacher auf den eingebundenen Pfad zuzugreifen.

Hinweis

Verwenden Sie FileDatasets nur für „side_inputs“.

local_path = "/tmp/{}".format(str(uuid.uuid4()))
label_config = label_ds.as_named_input("labels_input").as_mount(local_path)
batch_score_step = ParallelRunStep(
    name=parallel_step_name,
    inputs=[input_images.as_named_input("input_images")],
    output=output_dir,
    arguments=["--labels_dir", label_config],
    side_inputs=[label_config],
    parallel_run_config=parallel_run_config,
)

Danach können Sie in Ihrem Skript (z. B. in Ihrer init()-Methode) wie folgt darauf zugreifen:

parser = argparse.ArgumentParser()
parser.add_argument('--labels_dir', dest="labels_dir", required=True)
args, _ = parser.parse_known_args()

labels_path = args.labels_dir

Wie werden Eingabedatasets mit Dienstprinzipalauthentifizierung verwendet?

Der Benutzer kann Eingabedatasets mit Dienstprinzipalauthentifizierung übergeben, die im Arbeitsbereich verwendet werden. Damit ein solches Dataset in ParallelRunStep verwendet werden kann, muss das Dataset dafür registriert werden, damit die ParallelRunStep-Konfiguration erstellt werden kann.

service_principal = ServicePrincipalAuthentication(
    tenant_id="***",
    service_principal_id="***",
    service_principal_password="***")

ws = Workspace(
    subscription_id="***",
    resource_group="***",
    workspace_name="***",
    auth=service_principal
    )

default_blob_store = ws.get_default_datastore() # or Datastore(ws, '***datastore-name***')
ds = Dataset.File.from_files(default_blob_store, '**path***')
registered_ds = ds.register(ws, '***dataset-name***', create_new_version=True)

Überprüfen und Analysieren des Fortschritts

In diesem Abschnitt erfahren Sie, wie Sie den Fortschritt eines ParallelRunStep-Auftrags überprüfen und die Ursache für unerwartetes Verhalten untersuchen können.

Überprüfen des Auftragsfortschritts

Neben dem Gesamtstatus von StepRun können Sie in ~/logs/job_progress_overview.<timestamp>.txt die Anzahl der geplanten/verarbeiteten Minibatches und den Fortschritt der Ausgabegenerierung anzeigen. Die Datei wird täglich rotiert. Sie können die Datei mit dem größten Zeitstempel auf die neuesten Informationen überprüfen.

Was sollte ich überprüfen, wenn es eine Weile keinen Fortschritt gibt?

Sie können zu ~/logs/sys/error wechseln, um festzustellen, ob eine Ausnahme ausgelöst wurde. Wenn keine ausgelöst wurde, nimmt Ihr Einstiegsskript wahrscheinlich viel Zeit in Anspruch. Sie können Fortschrittsinformationen in Ihrem Code ausgeben, um den zeitintensiven Teil zu ermitteln, oder "--profiling_module", "cProfile" in den arguments von ParallelRunStep hinzufügen, um ein Profil namens <process_name>.profile im Ordner ~/logs/sys/node/<node_id> zu generieren.

Wann wird ein Auftrag beendet?

Wenn kein Abbruch erfolgt, wird der Auftrag mit folgendem Status beendet:

  • Abgeschlossen. Alle Minibatches wurden erfolgreich verarbeitet, und für den append_row-Modus wurde eine Ausgabe generiert.
  • Fehlerhaft. error_threshold in Parameters for ParallelRunConfig wurde überschritten, oder während des Auftrags ist ein Systemfehler aufgetreten.

Wo finde ich die Ursache eines Fehlers?

Sie können dem Lead in ~/logs/job_result.txt folgen, um die Ursache und das ausführliche Fehlerprotokoll zu finden.

Wirkt sich ein Knotenfehler auf das Auftragsergebnis aus?

Nicht, wenn im angegebenen Computecluster andere verfügbare Knoten vorhanden sind. ParallelRunStep kann unabhängig auf jedem Knoten ausgeführt werden. Fehler eines einzelnen Knotens führen nicht dazu, dass der gesamte Auftrag fehlschlägt.

Was passiert, wenn die init-Funktion im Einstiegsskript Fehler verursacht?

ParallelRunStep bietet einen Mechanismus zur Wiederholung eines bestimmten Zeitraums, um nach vorübergehenden Problemen eine Wiederherstellung zu ermöglichen, ohne den Auftragsfehler zu lange hinauszuzögern. Der Mechanismus funktioniert wie folgt:

  1. Wenn init nach dem Starten eines Knotens auf allen Agents kontinuierlich Fehler verursacht, werden alle weiteren Versuche nach 3 * process_count_per_node-Fehlern beendet.
  2. Wenn init nach dem Starten des Auftrags auf allen Agents aller Knoten kontinuierlich fehlschlägt, werden alle weiteren Versuche aufgegeben, wenn der Auftrag länger als 2 Minuten ausgeführt wird und 2 * node_count * process_count_per_node Fehler auftreten.
  3. Wenn alle Agents länger als init Sekunden bei 3 * run_invocation_timeout + 30 hängen bleiben, löst der Auftrag Fehler aus, da es zu lange keinen Fortschritt gab.

Was passiert bei OutOfMemory? Wie kann ich die Ursache überprüfen?

Der Prozess wurde möglicherweise vom System beendet. ParallelRunStep legt den aktuellen Versuch, den Minibatch zu verarbeiten, auf einen Fehlerstatus fest und versucht, den fehlerhaften Prozess neu zu starten. Sie können in ~logs/perf/<node_id> nach dem speicherintensiven Prozess suchen.

Warum habe ich viele processNNN-Dateien?

ParallelRunStep startet neue Workerprozesse, um die nicht ordnungsgemäß beendeten zu ersetzen. Außerdem generiert jeder Prozess mehrere processNNN-Dateien als Protokolle. Wenn der Prozess jedoch aufgrund einer Ausnahme während der init-Funktion des Benutzerskripts nicht ausgeführt werden konnte und sich dieser Fehler kontinuierlich 3 * process_count_per_node Male wiederholte, wird kein neuer Workerprozess gestartet.

Nächste Schritte