Monitora i carichi di lavoro di apprendimento per rinforzo su GKE

Questo documento mostra come emettere, raccogliere e visualizzare metriche e tracce chiave per le applicazioni di apprendimento per rinforzo (RL) basate su Python in esecuzione su Google Kubernetes Engine (GKE).

Questo documento mostra come:

  • Instrumenta l'applicazione RL per emettere metriche e tracce. L'instrumentazione utilizzata è per metriche e tracce che seguono il formato OpenTelemetry.
  • Raccogli metriche e tracce quando l'applicazione viene eseguita su GKE. I dati vengono raccolti utilizzando Managed OpenTelemetry per GKE (anteprima).
  • Visualizza le metriche raccolte in Cloud Monitoring e le tracce in Cloud Trace.
  • Identifica e comprendi le metriche RL critiche in base alle convenzioni semantiche e ai segnali d'oro di OpenTelemetry. I segnali d'oro sono le quattro metriche chiave di un servizio che forniscono una panoramica di alto livello del suo stato: latenza, traffico, errori e saturazione.

Prima di iniziare

  1. Assicurati di avere un'applicazione RL basata su Python che vuoi monitorare utilizzando metriche e dati di tracciamento.

  2. Assicurati di avere un progetto Google Cloud con la fatturazione abilitata.

  3. Devi disporre di un cluster GKE che esegue la versione 1.34.1-gke.2178000 o successive di GKE, che sono le versioni in cui è disponibile Managed OpenTelemetry per GKE (anteprima).

  4. Abilita le seguenti API Google Cloud :

    • container.googleapis.com (GKE)
    • monitoring.googleapis.com (monitoraggio)
    • cloudtrace.googleapis.com (Trace)
    • telemetry.googleapis.com (API OpenTelemetry Telemetry)

    Puoi abilitare queste API utilizzando gcloud:

    gcloud services enable \
        container.googleapis.com \
        monitoring.googleapis.com \
        cloudtrace.googleapis.com \
        telemetry.googleapis.com
    
  5. Installa l'SDK OpenTelemetry: nell'ambiente dell'applicazione Python RL, installa l'SDK OpenTelemetry e l'esportatore OTLP:

    pip install opentelemetry-sdk \
                opentelemetry-exporter-otlp-proto-grpc \
                opentelemetry-api
    

    Potresti anche aver bisogno di librerie di strumentazione per tutti i framework utilizzati dalla tua app RL, ad esempio opentelemetry-instrumentation-flask.

Costi

Quando invii dati di telemetria a Google Cloud, la fatturazione viene eseguita in base al volume di importazione. Le metriche vengono fatturate in base ai prezzi di Google Cloud Managed Service per Prometheus, i log vengono fatturati in base ai prezzi di Cloud Logging e le tracce vengono fatturate in base ai prezzi di Cloud Trace.

Per informazioni sui costi associati all'importazione di trace, log e metriche di Google Cloud Managed Service per Prometheus, consulta Prezzi di Google Cloud Observability.

Instrumentare l'applicazione con OpenTelemetry

Strumenta il codice dell'applicazione Python RL in modo che possa emettere metriche OpenTelemetry. Per instrumentare l'applicazione:

  1. Inizializza OpenTelemetry aggiungendo il seguente codice all'applicazione:

    import os
    import time
    from opentelemetry import metrics, trace
    from opentelemetry.sdk.metrics import MeterProvider
    from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
    from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
    from opentelemetry.sdk.trace import TracerProvider
    from opentelemetry.sdk.trace.export import BatchSpanProcessor
    from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
    from opentelemetry.sdk.resources import Resource
    from opentelemetry.metrics import Counter, Histogram, UpDownCounter
    
    resource = Resource.create({
        "service.name": "rl-training-service",
        "service.namespace": "opentelemetry-demo",
    })
    
    # Initialize Metrics
    reader = PeriodicExportingMetricReader(
        OTLPMetricExporter(
            endpoint=os.environ.get("OTEL_EXPORTER_OTLP_METRICS_ENDPOINT", "localhost:4317"),
            insecure=True
        )
    )
    meter_provider = MeterProvider(metric_readers=[reader], resource=resource)
    metrics.set_meter_provider(meter_provider)
    meter = metrics.get_meter("rl-training-meter")
    
    # Initialize Tracing
    trace_provider = TracerProvider(resource=resource)
    trace_processor = BatchSpanProcessor(
        OTLPSpanExporter(
            endpoint=os.environ.get("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT", "localhost:4317"),
            insecure=True
        )
    )
    trace_provider.add_span_processor(trace_processor)
    trace.set_tracer_provider(trace_provider)
    tracer = trace.get_tracer("rl-training-tracer")
    
  2. Crea strumenti per ogni metrica e registra i valori che vuoi che vengano emessi dall'applicazione. Allega le convenzioni semantiche pertinenti come attributi.

    Utilizza l'elenco delle convenzioni semantiche e dei segnali aurei per determinare quali metriche instrumentare per la tua applicazione.

    Di seguito è riportato un esempio di strumenti per metriche specifiche:

    # Latency Histograms
    rl_loop_duration = meter.create_histogram(
        name="rl.loop.duration", description="Duration of a single RL loop iteration.", unit="ms"
    )
    rl_sample_duration = meter.create_histogram(
        name="rl.sample.duration", description="Duration of the sampling phase.", unit="ms"
    )
    rl_train_duration = meter.create_histogram(
        name="rl.train.duration", description="Duration of the training phase.", unit="ms"
    )
    # ... create other duration histograms (reward, train, sync, step)
    
    # Throughput Counters
    rl_sample_samples = meter.create_counter(
        name="rl.sample.samples", description="Number of samples generated.", unit="{samples}"
    )
    rl_train_steps = meter.create_counter(
        name="rl.train.steps", description="Number of training steps completed.", unit="{steps}"
    )
    # ... create other counter metrics (rl.sample.episodes, rl.train.tokens)
    
    # Performance/Saturation Gauges (using UpDownCounter)
    rl_reward_mean = meter.create_up_down_counter(
        name="rl.environment.reward.mean", description="Mean reward observed.", unit="1"
    )
    rl_train_loss = meter.create_up_down_counter(
        name="rl.train.loss", description="Current training loss.", unit="1"
    )
    rl_train_mfu = meter.create_up_down_counter(
        name="rl.train.mfu", description="Model Flop Utilization.", unit="1"
    )
    _rl_reward_mean_val, _rl_train_loss_val = 0.0, 0.0
    
    def get_common_attributes(rl_system, rl_run_id, rl_algorithm, rl_env_name, rl_model_name):
        return {
            "rl.system": rl_system,
            "rl.run.id": rl_run_id,
            "rl.algorithm": rl_algorithm,
            "rl.environment.name": rl_env_name,
            "rl.model.name": rl_model_name,
        }
    
    # Example Usage within your RL code:
    common_attrs = get_common_attributes("MyPPO", "run-42", "PPO", "Acrobot-v1", "PolicyModelV1")
    
    # Inside the main RL loop:
    with tracer.start_as_current_span("rl_loop_iteration", attributes={**common_attrs, "rl.loop.iteration": 5}) as span:
        loop_start_time = time.perf_counter()
    # --- Sampling Phase ---
    sample_start = time.perf_counter()
    # ... perform sampling ...
    sampled_count = 1024
    rl_sample_samples.add(sampled_count, attributes={**common_attrs, "rl.sample.batch_size": 128})
    rl_sample_duration.record((time.perf_counter() - sample_start) * 1000, attributes=common_attrs)
    
    # --- Training Phase ---
    train_start = time.perf_counter()
    # ... perform training step ...
    rl_train_steps.add(1, attributes={**common_attrs, "rl.loop.iteration": 5})
    current_loss = 0.125
    rl_train_loss.add(current_loss - _rl_train_loss_val, attributes=common_attrs) # Record current loss
    _rl_train_loss_val = current_loss
    rl_train_duration.record((time.perf_counter() - train_start) * 1000, attributes=common_attrs)
    
    # --- Record Mean Reward ---
    current_mean_reward = -5.5
    rl_reward_mean.add(current_mean_reward - _rl_reward_mean_val, attributes=common_attrs)
    _rl_reward_mean_val = current_mean_reward
    
    loop_duration = (time.perf_counter() - loop_start_time) * 1000
    rl_loop_duration.record(loop_duration, attributes={**common_attrs, "rl.loop.iteration": 5})
    
    # Ensure metrics are pushed before application exit in short-lived scripts
    # For long-running services, PeriodicExportingMetricReader handles this.
    # meter_provider.shutdown()
    

Ora che hai inizializzato OpenTelemetry e creato strumenti per metriche specifiche, l'applicazione emette i dati di telemetria specificati quando viene eseguita.

Abilita la raccolta di metriche e dati di traccia in GKE

Per raccogliere i dati di telemetria emessi dall'applicazione durante l'esecuzione, puoi utilizzare Managed OpenTelemetry per GKE (anteprima). Questa funzionalità raccoglie dati di telemetria, come metriche e tracce, e li invia a Google Cloud Observability.

Per abilitare e configurare Managed OpenTelemetry per GKE, procedi nel seguente modo:

  1. Abilita OpenTelemetry gestito per GKE sul cluster in cui viene eseguita l'applicazione. Per farlo, segui i passaggi descritti in Abilitare OpenTelemetry gestito per GKE in un cluster.

  2. Aggiungi annotazioni al deployment dell'applicazione con variabili di ambiente per indirizzare l'SDK OpenTelemetry a inviare dati di telemetria all'endpoint OTLP dell'agente di raccolta gestito. Per un'applicazione RL basata su Python, non puoi utilizzare la funzionalità di configurazione automatica di Managed OpenTelemetry per GKE.

    Aggiungi invece la seguente sezione env alla specifica del container nel manifest del deployment:

    env:
      - name: OTEL_COLLECTOR_NAME
        value: 'opentelemetry-collector'
      - name: OTEL_COLLECTOR_NAMESPACE
        value: 'gke-managed-otel'
      - name: OTEL_EXPORTER_OTLP_METRICS_ENDPOINT
        value: $(OTEL_COLLECTOR_NAME).$(OTEL_COLLECTOR_NAMESPACE).svc.cluster.local:4317
      - name: OTEL_EXPORTER_OTLP_TRACES_ENDPOINT
        value: $(OTEL_COLLECTOR_NAME).$(OTEL_COLLECTOR_NAMESPACE).svc.cluster.local:4317
      - name: OTEL_SERVICE_NAME
        value: 'rl-training-service'
      - name: OTEL_RESOURCE_ATTRIBUTES
        value: service.namespace=opentelemetry-demo
    

Ora che l'applicazione è strumentata e l'agente di raccolta gestito è abilitato e configurato, quando l'applicazione viene eseguita sul cluster GKE, le metriche e le tracce vengono inviate a Google Cloud Observability.

Puoi visualizzare questi dati di telemetria in Monitoring e Trace.

Visualizzare le metriche in Monitoring

Una volta che l'applicazione RL è in esecuzione su GKE con Managed OpenTelemetry abilitato, le metriche vengono inviate a Monitoring. Le metriche sono in genere disponibili nel dominio prometheus.googleapis.com/.

Per visualizzare le metriche RL personalizzate in Monitoring:

  1. Per visualizzare le metriche RL in una dashboard, puoi:

  2. Nel campo Metrica della dashboard, cerca le metriche che iniziano con prometheus.googleapis.com/. Le metriche disponibili corrispondono a quelle instrumentate nell'applicazione. Ecco alcuni esempi di queste metriche:

    • prometheus.googleapis.com/rl_loop_duration_histogram/
    • prometheus.googleapis.com/rl_sample_samples_total/
    • prometheus.googleapis.com/rl_environment_reward_mean_total/
  3. Filtro e raggruppamento:puoi utilizzare i filtri in Metrics Explorer per sfruttare le convenzioni semantiche che hai aggiunto come attributi. Ad esempio, quanto segue specifica la durata del ciclo per una corsa e un algoritmo specifici:

    • Filtro: metric.label."rl_run_id" == "run-42"
    • Filtro: metric.label."rl_algorithm" == "PPO"
    • Raggruppa per: metric.label."rl_environment_name" per confrontare il rendimento nei vari ambienti.

Visualizzare le tracce in Trace

Le tracce distribuite forniscono una sequenza temporale delle operazioni e ti aiutano a eseguire il debug del flusso di esecuzione all'interno del sistema RL.

  1. Nella console Google Cloud , apri Esplora tracce nella console Google Cloud :

    Vai alla pagina Esplora tracce

  2. Puoi eseguire query e filtrare le tracce. Poiché hai impostato "service.name": "rl-training-service" come attributo della risorsa, puoi filtrare le tracce in base a resource.labels.service_name="rl-training-service".

    I singoli intervalli all'interno di una traccia rappresentano diverse parti del carico di lavoro RL. Questi intervalli potrebbero includere chiamate a servizi esterni o diverse fasi del ciclo RL, a seconda di come hai instrumentato la tracciabilità nell'applicazione.

Convenzioni semantiche RL e indicatori aurei

Questa sezione elenca le metriche OpenTelemetry che possono aiutarti a identificare i problemi che si verificano durante l'esecuzione dell'applicazione RL su GKE.

Utilizza le informazioni in questa sezione per:

  • Decidi quali metriche e tracce raccogliere per la tua applicazione.
  • Decidi come visualizzare e utilizzare le metriche e i dati di traccia raccolti dalla tua applicazione.

Per monitorare in modo efficace i carichi di lavoro RL utilizzando OpenTelemetry, è utile concentrarsi sui "segnali d'oro". Gli indicatori aurei sono le quattro metriche chiave di un servizio che forniscono una panoramica di alto livello del suo stato: latenza, traffico, errori e saturazione. Se strumenti la tua applicazione RL con queste metriche, puoi comprendere ed eseguire il debug rapidamente dei problemi di prestazioni.

Le sezioni seguenti contengono le convenzioni semantiche e i nomi delle metriche classificati in base agli indicatori chiave che rappresentano in un contesto RL.

Convenzioni semantiche RL

Di seguito sono riportati gli attributi delle metriche. Questi attributi forniscono il contesto per il filtraggio e l'analisi in Monitoring.

  • RL_SYSTEM = "rl.system": il nome del sistema o del framework RL (ad esempio, "MyCustomRL").
  • RL_SYSTEM_VERSION = "rl.system.version": versione del sistema RL.
  • RL_RUN_ID = "rl.run.id": identificatore univoco di una sessione di addestramento specifica.
  • RL_ALGORITHM = "rl.algorithm": l'algoritmo RL utilizzato (ad esempio, "PPO", "DQN").
  • RL_ENVIRONMENT_NAME = "rl.environment.name": il nome dell'ambiente RL (ad esempio, "CartPole-v1").
  • RL_MODEL_NAME = "rl.model.name": il nome o l'identificatore del modello di policy/valore.
  • RL_LOOP = "rl.loop": identificatore del ciclo di addestramento principale.
  • RL_LOOP_ITERATION = "rl.loop.iteration": numero di iterazione corrente del ciclo RL.
  • RL_SAMPLE = "rl.sample": contesto per la fase di campionamento.
  • RL_SAMPLE_EPISODES = "rl.sample.episodes": numero di episodi campionati.
  • RL_SAMPLE_STEPS = "rl.sample.steps": numero di passaggi campionati.
  • RL_SAMPLE_BATCH_SIZE = "rl.sample.batch_size": dimensione del batch utilizzata durante il campionamento.
  • RL_REWARD = "rl.reward": contesto per il calcolo della ricompensa.
  • RL_REWARD_BATCH_SIZE = "rl.reward.batch_size": dimensione del batch per il calcolo della ricompensa.
  • RL_REWARD_SANDBOX = "rl.reward.sandbox": identificatore della sandbox di calcolo della ricompensa.
  • RL_TRAIN = "rl.train": contesto per la fase di addestramento.
  • RL_TRAIN_STEPS = "rl.train.steps": numero di passaggi di addestramento.
  • RL_TRAIN_BATCH_SIZE = "rl.train.batch_size": dimensione del batch utilizzata durante l'addestramento.
  • RL_TRAIN_TOKENS = "rl.train.tokens": numero di token elaborati durante l'addestramento.
  • RL_SYNC = "rl.sync": contesto per le operazioni di sincronizzazione.
  • RL_SYNC_BYTES = "rl.sync.bytes": byte trasferiti durante la sincronizzazione.
  • RL_SYNC_SOURCE = "rl.sync.source": origine della sincronizzazione.
  • RL_SYNC_DESTINATION = "rl.sync.destination": destinazione della sincronizzazione.

Segnali aurei e metriche RL

Le sezioni seguenti elencano le metriche RL correlate ai quattro segnali d'oro: latenza, traffico, errori e saturazione.

Per informazioni dettagliate sui segnali aurei, vedi I quattro segnali aurei nel capitolo 6 del libro Site Reliability Engineering (SRE) di Google.

Latenza

Quanto tempo è necessario per completare le operazioni relative alle chiavi? Una latenza elevata può indicare ritardi nel completamento delle operazioni principali. Le seguenti metriche possono aiutarti a identificare eventuali problemi di latenza che si verificano durante l'esecuzione dell'applicazione RL su GKE.

  • rl.loop.duration (istogramma): una durata elevata del ciclo rallenta l'intero processo di addestramento. Il monitoraggio di questo valore aiuta a identificare le regressioni del rendimento in qualsiasi parte del ciclo di RL.
  • rl.sample.duration (Istogramma): il campionamento lento influisce direttamente sulla velocità con cui vengono generati nuovi dati per l'addestramento.
  • rl.reward.duration (Istogramma): il calcolo della ricompensa può essere complesso; il monitoraggio della sua latenza aiuta a ottimizzare questo passaggio fondamentale.
  • rl.train.duration (istogramma): il tempo di addestramento è fondamentale per la velocità di iterazione. I picchi in questo grafico possono indicare problemi nell'algoritmo di addestramento o nell'hardware.
  • rl.sync.duration (Istogramma): la sincronizzazione efficiente è fondamentale nell'apprendimento per rinforzo distribuito. Tempi di sincronizzazione lunghi possono causare dati obsoleti e rallentare l'apprendimento.
  • rl.step.duration (Istogramma): latenza granulare dei singoli passaggi dell'ambiente.

Traffico e velocità effettiva

Quanto lavoro viene svolto? Una velocità effettiva bassa può significare un utilizzo inefficiente delle risorse. Le seguenti metriche possono aiutarti a identificare eventuali problemi di traffico o velocità effettiva che si verificano durante l'esecuzione dell'applicazione RL su GKE.

  • rl.sample.samples (Contatore): rappresenta il volume dei dati sull'esperienza raccolti. Un calo indica problemi nel processo di campionamento.
  • rl.sample.episodes (contatore): tiene traccia del numero di puntate complete riprodotte.
  • rl.train.steps (Contatore): misura l'avanzamento dell'addestramento in termini di passaggi di ottimizzazione.
  • rl.train.tokens (contatore): tiene traccia del numero totale di token elaborati. Questa metrica è pertinente per l'RL dei modelli di grandi dimensioni.
  • rl.tokens.rate / rl.tokens.rate_per_gpu (misura/velocità): misure dirette della velocità e dell'efficienza dell'addestramento, in particolare nei modelli basati su token.
  • rl.samples.rate / rl.samples.rate_per_gpu (indicatore/velocità): misura la velocità con cui il sistema raccoglie nuovi campioni.

Errori

Sono presenti errori di rendimento o di esecuzione? Nell'RL, gli "errori" possono manifestarsi come comportamenti imprevisti o prestazioni scadenti. Le seguenti metriche possono aiutarti a identificare eventuali errori che si verificano durante l'esecuzione dell'applicazione RL su GKE.

  • rl.environment.reward.mean (indicatore): sebbene non si tratti di un errore tradizionale, un calo drastico della ricompensa media è un segnale critico che indica che qualcosa non va nell'interazione tra l'agente e l'ambiente. Questa metrica riflette direttamente i progressi di apprendimento e il rendimento dell'agente.
  • rl.environment.episode.length.mean (Indicatore): simile alla ricompensa, cambiamenti imprevisti nella durata dell'episodio possono segnalare problemi.
  • rl.train.loss (Indicatore): un aumento improvviso o un comportamento irregolare della perdita di addestramento indica che il modello non sta apprendendo in modo efficace. Indicatore fondamentale della stabilità e del successo dell'allenamento.

Saturazione

Il sistema è sovraccarico? Una saturazione elevata può comportare un peggioramento delle prestazioni. La seguente metrica può aiutarti a identificare eventuali problemi di saturazione che si verificano durante l'esecuzione dell'applicazione RL su GKE.

  • rl.train.mfu (indicatore): utilizzo del modello flop (MFU). Indica l'efficacia con cui le risorse di calcolo (come GPU o TPU) vengono utilizzate durante l'addestramento. Un valore MFU basso suggerisce un sottoutilizzo o colli di bottiglia.

Passaggi successivi