מעקב אחרי עומסי עבודה של למידת חיזוק ב-GKE

במאמר הזה נסביר איך לשלוח, לאסוף ולהציג מדדים חשובים ועקבות של אפליקציות ללמידת חיזוקים (RL) שמבוססות על Python ופועלות ב-Google Kubernetes Engine ‏ (GKE).

במאמר הזה מוסבר איך:

  • לבצע אינסטרומנטציה לאפליקציה של RL כך שתפלוט מדדים ועקבות. השדרוג שבו נעשה שימוש הוא למדדים ולמעקבים בפורמט OpenTelemetry.
  • איסוף מדדים ועקבות כשהאפליקציה פועלת ב-GKE. הנתונים נאספים באמצעות Managed OpenTelemetry for GKE ‏ (תצוגה מקדימה).
  • אפשר לראות את המדדים שנאספו ב-Cloud Monitoring ואת העקבות ב-Cloud Trace.
  • זיהוי והבנה של מדדים קריטיים של RL על סמך מוסכמות סמנטיות של OpenTelemetry ואותות מהימנים. האותות המוזהבים הם ארבעת מדדי המפתח של שירות שמספקים סקירה כללית של מצב השירות: זמן טעינה, תנועת גולשים, שגיאות ורוויה.

לפני שמתחילים

  1. מוודאים שיש לכם אפליקציית RL מבוססת-Python שאתם רוצים לעקוב אחריה באמצעות מדדים ונתוני מעקב.

  2. מוודאים שיש לכם פרויקט ב- Cloud de Confiance by S3NS שהחיוב בו מופעל.

  3. צריך אשכול GKE שפועלת בו גרסה ‎1.34.1-gke.2178000 של GKE ומעלה. אלה הגרסאות שבהן זמין Managed OpenTelemetry ל-GKE (גרסת טרום-השקה).

  4. מפעילים את ממשקי ה- Cloud de Confiance API הבאים:

    • ‫container.googleapis.com (GKE)
    • monitoring.googleapis.com (מעקב)
    • ‫cloudtrace.googleapis.com (Trace)
    • ‫telemetry.googleapis.com (OpenTelemetry Telemetry API)

    אפשר להפעיל את ממשקי ה-API האלה באמצעות gcloud:

    gcloud services enable \
        container.googleapis.com \
        monitoring.googleapis.com \
        cloudtrace.googleapis.com \
        telemetry.googleapis.com
    
  5. מתקינים את OpenTelemetry SDK: בסביבה של אפליקציית Python RL, מתקינים את OpenTelemetry SDK ואת OTLP Exporter:

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

    יכול להיות שתצטרכו גם ספריות של כלי מדידה לכל המסגרות שבהן נעשה שימוש באפליקציית ה-RL, למשל opentelemetry-instrumentation-flask.

עלויות

כששולחים נתוני טלמטריה אל Cloud de Confiance, החיוב הוא לפי נפח ההטמעה. החיוב על מדדים מתבצע לפי התמחור של השירות המנוהל של Google Cloud ל-Prometheus, החיוב על יומנים מתבצע לפי התמחור של Cloud Logging והחיוב על עקבות מתבצע לפי התמחור של Cloud Trace.

למידע על העלויות שקשורות להוספה של נתונים של מעקב, יומנים ומדדים של השירות המנוהל של Google Cloud ל-Prometheus, ראו תמחור של Google Cloud Observability.

לבצע אינסטרומנטציה לאפליקציה באמצעות OpenTelemetry

מוסיפים אינסטרומנטציה לקוד של אפליקציית Python RL כדי שהיא תוכל לפלוט מדדים של OpenTelemetry. כדי להוסיף לאפליקציה קוד למעקב:

  1. מאתחלים את OpenTelemetry על ידי הוספת הקוד הבא לאפליקציה:

    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. יוצרים מכשירים לכל מדד ומתעדים את הערכים שרוצים שהאפליקציה תפיק. מצרפים מוסכמות סמנטיות רלוונטיות בתור מאפיינים.

    אפשר להשתמש ברשימה של מוסכמות סמנטיות ואותות חשובים כדי לקבוע אילו מדדים להגדיר לאפליקציה.

    דוגמה למכשירים למדדים ספציפיים:

    # 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()
    

אחרי שאתחלתם את OpenTelemetry ויצרתם מכשירים למדדים ספציפיים, האפליקציה פולטת את נתוני הטלמטריה שצוינו כשהיא פועלת.

הפעלה של איסוף מדדים ונתוני מעקב ב-GKE

כדי לאסוף את נתוני הטלמטריה שהאפליקציה פולטת בזמן שהיא פועלת, אפשר להשתמש ב-Managed OpenTelemetry for GKE ‏ (Preview). התכונה הזו אוספת נתוני טלמטריה, כמו מדדים ועקבות, ושולחת את הנתונים אל Google Cloud Observability.

כדי להפעיל ולהגדיר את Managed OpenTelemetry ל-GKE:

  1. מפעילים את Managed OpenTelemetry ל-GKE באשכול שבו האפליקציה פועלת. כדי לעשות זאת, פועלים לפי השלבים במאמר בנושא הפעלת OpenTelemetry מנוהל ל-GKE באשכול.

  2. מוסיפים הערות לפריסת האפליקציה עם משתני סביבה כדי להנחות את OpenTelemetry SDK לשלוח נתוני טלמטריה לנקודת הקצה של OTLP של האוסף המנוהל. באפליקציית RL מבוססת Python, אי אפשר להשתמש בתכונת ההגדרה האוטומטית מ-Managed OpenTelemetry ל-GKE.

    במקום זאת, מוסיפים את הקטע env הבא למפרט של הקונטיינר במניפסט הפריסה:

    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
    

עכשיו, אחרי שהאפליקציה מוגדרת, והאוסף המנוהל מופעל ומוגדר, כשהאפליקציה פועלת באשכול GKE, המדדים והעקבות נשלחים אל Google Cloud Observability.

אפשר לראות את נתוני הטלמטריה האלה ב-Monitoring וב-Trace.

הצגת מדדים במעקב

אחרי שהאפליקציה שלכם ללמידת חיזוקים פועלת ב-GKE עם OpenTelemetry מנוהל מופעל, המדדים נשלחים ל-Monitoring. המדדים זמינים בדרך כלל בדומיין prometheus.googleapis.com/.

כדי לראות את מדדי ה-RL המותאמים אישית ב-Monitoring:

  1. כדי לראות את מדדי ה-RL בלוח בקרה, אפשר לבצע אחת מהפעולות הבאות:

  2. בשדה Metric של לוח הבקרה, מחפשים מדדים שמתחילים ב-prometheus.googleapis.com/. המדדים שזמינים תואמים למדדים שהטמעתם באפליקציה. דוגמאות למדדים האלה:

    • prometheus.googleapis.com/rl_loop_duration_histogram/
    • prometheus.googleapis.com/rl_sample_samples_total/
    • prometheus.googleapis.com/rl_environment_reward_mean_total/
  3. סינון וקיבוץ: אתם יכולים להשתמש במסננים ב-Metrics Explorer כדי להשתמש במוסכמות הסמנטיות שהוספתם כמאפיינים. לדוגמה, ההגדרה הבאה מציינת את משך הלולאה לריצה ולאלגוריתם ספציפיים:

    • מסנן: metric.label."rl_run_id" == "run-42"
    • מסנן: metric.label."rl_algorithm" == "PPO"
    • קיבוץ לפי: metric.label."rl_environment_name" כדי להשוות בין הביצועים בסביבות שונות.

צפייה בעקבות ב-Trace

המעקב המבוזר מספק ציר זמן של פעולות ועוזר לכם לנפות באגים בזרימת הביצוע במערכת RL.

  1. במסוף Cloud de Confiance , פותחים את Trace Explorer במסוף Cloud de Confiance :

    מעבר לדף Trace Explorer

  2. אפשר להריץ שאילתות ולסנן עקבות. הגדרתם את "service.name": "rl-training-service" כמאפיין משאב, ולכן אתם יכולים לסנן את העקבות לפי resource.labels.service_name="rl-training-service".

    כל טווח בתוך מעקב מייצג חלקים שונים בעומס העבודה של RL. הטווחים האלה יכולים לכלול קריאות לשירותים חיצוניים או שלבים שונים בלולאת RL, בהתאם לאופן שבו הגדרתם את המעקב באפליקציה.

מוסכמות סמנטיות ואותות הזהב של RL

בקטע הזה מפורטים מדדים של OpenTelemetry שיכולים לעזור לכם לזהות בעיות שמתרחשות בזמן שאפליקציית RL פועלת ב-GKE.

המידע בקטע הזה יכול לעזור לכם:

  • מחליטים אילו מדדים ועקבות לאסוף עבור האפליקציה.
  • קובעים איך להציג את המדדים ואת נתוני המעקב שנאספו מהאפליקציה ואיך להשתמש בהם.

כדי לעקוב ביעילות אחרי עומסי עבודה של RL באמצעות OpenTelemetry, מומלץ להתמקד ב'אותות הזהב'. האותות המוזהבים הם ארבעת המדדים העיקריים של שירות שמספקים סקירה כללית של תקינות השירות: זמן אחזור, תנועה, שגיאות ורוויה. הוספת המדדים האלה לאפליקציית ה-RL מאפשרת להבין במהירות בעיות בביצועים ולנפות באגים.

בקטעים הבאים מפורטים המוסכמות הסמנטיות ושמות המדדים שמסווגים לפי האותות המוזהבים שהם מייצגים בהקשר של RL.

מוסכמות סמנטיות של RL

אלה המאפיינים של המדדים. המאפיינים האלה מספקים הקשר לסינון ולניתוח ב'מעקב'.

  • ‫RL_SYSTEM = "rl.system": השם של מערכת או מסגרת ה-RL (לדוגמה, MyCustomRL).
  • ‫RL_SYSTEM_VERSION = "rl.system.version": גרסת מערכת ה-RL.
  • ‫RL_RUN_ID = "rl.run.id": מזהה ייחודי של הרצת אימון ספציפית.
  • ‫RL_ALGORITHM = "rl.algorithm": אלגוריתם ה-RL שבו נעשה שימוש (לדוגמה, "PPO",‏ "DQN").
  • ‫RL_ENVIRONMENT_NAME = "rl.environment.name": השם של סביבת RL (לדוגמה, CartPole-v1).
  • ‫RL_MODEL_NAME = "rl.model.name": השם או המזהה של מודל המדיניות או הערך.
  • ‫RL_LOOP = "rl.loop": מזהה של לולאת האימון הראשית.
  • ‫RL_LOOP_ITERATION = "rl.loop.iteration": מספר האיטרציה הנוכחית של לולאת RL.
  • ‫RL_SAMPLE = "rl.sample": הקשר של שלב הדגימה.
  • ‫RL_SAMPLE_EPISODES = "rl.sample.episodes": מספר הפרקים שנדגמו.
  • ‫RL_SAMPLE_STEPS = "rl.sample.steps": מספר השלבים שנדגמו.
  • ‫RL_SAMPLE_BATCH_SIZE = "rl.sample.batch_size": גודל האצווה שנעשה בו שימוש במהלך הדגימה.
  • ‫RL_REWARD = rl.reward: הקשר לחישוב התגמול.
  • ‫RL_REWARD_BATCH_SIZE = "rl.reward.batch_size": גודל אצווה לחישוב תגמול
  • ‫RL_REWARD_SANDBOX = "rl.reward.sandbox": מזהה של ארגז החול לחישוב תגמולים.
  • ‫RL_TRAIN = 'rl.train': הקשר לשלב האימון.
  • ‫RL_TRAIN_STEPS = "rl.train.steps": מספר שלבי האימון.
  • ‫RL_TRAIN_BATCH_SIZE = 'rl.train.batch_size': גודל אצווה שמשמש במהלך האימון.
  • ‫RL_TRAIN_TOKENS = "rl.train.tokens": מספר הטוקנים שעובדו במהלך האימון.
  • ‫RL_SYNC = "rl.sync": הקשר לפעולות סנכרון.
  • ‫RL_SYNC_BYTES = "rl.sync.bytes": בייטים שהועברו במהלך הסנכרון.
  • ‫RL_SYNC_SOURCE = "rl.sync.source": מקור הסנכרון.
  • ‫RL_SYNC_DESTINATION = "rl.sync.destination": יעד הסנכרון.

אותות הזהב ומדדי RL

בקטעים הבאים מפורטים מדדי RL שקשורים לארבעת האותות המרכזיים: השהיה, תנועה, שגיאות ורוויה.

לפרטים על אותות הזהב, אפשר לעיין במאמר ארבעת אותות הזהב בפרק 6 של הספר בנושא Site Reliability Engineering (SRE) של Google.

זמן אחזור

כמה זמן לוקח להשלים פעולות מרכזיות? חביון גבוה יכול להצביע על עיכובים בהשלמת פעולות מרכזיות. המדדים הבאים יכולים לעזור לכם לזהות בעיות של זמן אחזור שמתרחשות בזמן שהאפליקציה שלכם ל-RL פועלת ב-GKE.

  • ‫rl.loop.duration (היסטוגרמה): משך לולאה גבוה מאט את כל תהליך האימון. מעקב אחרי המדד הזה עוזר לזהות ירידות בביצועים בכל חלק במחזור החיים של ה-RL.
  • ‫rl.sample.duration (היסטוגרמה): דגימה איטית משפיעה ישירות על מהירות יצירת הנתונים החדשים לאימון.
  • ‫rl.reward.duration (היסטוגרמה): חישוב התגמול יכול להיות מורכב. מעקב אחרי זמן האחזור שלו עוזר לבצע אופטימיזציה של השלב הקריטי הזה.
  • ‫rl.train.duration (היסטוגרמה): זמן האימון הוא קריטי למהירות האיטרציה. נקודות שיא כאן יכולות להצביע על בעיות באלגוריתם האימון או בחומרה.
  • ‫rl.sync.duration (היסטוגרמה): סנכרון יעיל הוא חיוני ב-RL מבוזר. זמני סנכרון ארוכים עלולים לגרום לנתונים לא עדכניים ולהאט את תהליך הלמידה.
  • rl.step.duration (היסטוגרמה): חביון גרנולרי של שלבים סביבתיים נפרדים.

תעבורת נתונים ותפוקה

מה היקף העבודה שמתבצעת? תפוקה נמוכה יכולה להצביע על שימוש לא יעיל במשאבים. המדדים הבאים יכולים לעזור לכם לזהות בעיות בתנועה או ברוחב הפס שמתרחשות בזמן שהאפליקציה שלכם לחיזוק למידה (RL) פועלת ב-GKE.

  • ‫rl.sample.samples (מונה): מייצג את נפח נתוני החוויה שנאספו. ירידה מצביעה על בעיות בתהליך הדגימה.
  • ‫rl.sample.episodes (מונה): עוקב אחרי מספר הפרקים שהוצגו במלואם.
  • ‫rl.train.steps (מונה): מודד את התקדמות האימון במונחים של שלבי אופטימיזציה.
  • ‫rl.train.tokens (Counter): עוקב אחרי סך האסימונים שעברו עיבוד. המדד הזה רלוונטי ל-RL של מודלים גדולים.
  • ‫rl.tokens.rate / rl.tokens.rate_per_gpu (מדד/שיעור): מדדים ישירים של מהירות ויעילות האימון, במיוחד במודלים מבוססי-טוקנים.
  • ‫rl.samples.rate / rl.samples.rate_per_gpu (מדד/שיעור): מדד שבודק כמה מהר המערכת אוספת דגימות חדשות.

שגיאות

האם יש שגיאות בביצועים או בהפעלה? ב-RL, שגיאות יכולות להתבטא בהתנהגות לא צפויה או בביצועים ירודים. המדדים הבאים יכולים לעזור לכם לזהות שגיאות שמתרחשות בזמן שהאפליקציה שלכם ל-RL פועלת ב-GKE.

  • ‫rl.environment.reward.mean (מד): למרות שזו לא שגיאה מסורתית, ירידה דרמטית בתגמול הממוצע היא אות קריטי לכך שמשהו לא בסדר באינטראקציה של הסוכן או הסביבה. המדד הזה משקף באופן ישיר את התקדמות הלמידה ואת ביצועי הסוכן.
  • ‫rl.environment.episode.length.mean (מד): בדומה לתגמול, שינויים לא צפויים באורך הפרק יכולים להצביע על בעיות.
  • rl.train.loss (מד): עלייה פתאומית או התנהגות לא צפויה של הפסד האימון מצביעה על כך שהמודל לא לומד בצורה יעילה. מדד בסיסי ליציבות ההדרכה ולהצלחתה.

רוויה

המערכת עמוסה מדי? רוויה גבוהה עלולה לגרום לירידה בביצועים. המדד הבא יכול לעזור לכם לזהות בעיות שקשורות לרוויה שמתרחשות בזמן שהאפליקציה שלכם ללמידת חיזוק (RL) פועלת ב-GKE.

  • ‫rl.train.mfu (מד): ניצול Flop של המודל (MFU). מציין את מידת היעילות של השימוש במשאבי מחשוב (כמו GPU או TPU) במהלך האימון. ערך נמוך של MFU מצביע על ניצול חלקי או על צווארי בקבוק.

המאמרים הבאים