במאמר הזה נסביר איך לשלוח, לאסוף ולהציג מדדים חשובים ועקבות של אפליקציות ללמידת חיזוקים (RL) שמבוססות על Python ופועלות ב-Google Kubernetes Engine (GKE).
במאמר הזה מוסבר איך:
- לבצע אינסטרומנטציה לאפליקציית ה-RL כך שתפלוט מדדים ועקבות. האינסטרומנטציה שבה נעשה שימוש היא למדדים ולמעקבים בפורמט OpenTelemetry.
- איסוף מדדים ועקבות כשהאפליקציה פועלת ב-GKE. הנתונים נאספים באמצעות Managed OpenTelemetry for GKE (תצוגה מקדימה).
- אפשר לראות את המדדים שנאספו ב-Cloud Monitoring ואת העקבות ב-Cloud Trace.
- זיהוי והבנה של מדדי RL קריטיים על סמך מוסכמות סמנטיות של OpenTelemetry וסיגנלים מוזהבים. האותות המוזהבים הם ארבעת מדדי המפתח של שירות שמספקים סקירה כללית ברמה גבוהה של מצב השירות: זמן טעינה, תעבורה, שגיאות וניצול קיבולת.
לפני שמתחילים
מוודאים שיש לכם אפליקציית RL מבוססת-Python שאתם רוצים לנטר באמצעות מדדים ונתוני מעקב.
מוודאים שיש לכם פרויקט ב- Google Cloud שהחיוב מופעל בו.
צריך אשכול GKE שפועלת בו גרסה 1.34.1-gke.2178000 של GKE ומעלה. אלה הגרסאות שבהן זמין Managed OpenTelemetry ל-GKE (גרסת טרום-השקה).
מפעילים את ממשקי ה-API הבאים: Google Cloud
-
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-
מתקינים את OpenTelemetry SDK: בסביבה של אפליקציית ה-RL של Python, מתקינים את OpenTelemetry SDK ואת OTLP Exporter:
pip install opentelemetry-sdk \ opentelemetry-exporter-otlp-proto-grpc \ opentelemetry-apiיכול להיות שתצטרכו גם ספריות של מכשירי מדידה לכל המסגרות שבהן נעשה שימוש באפליקציית ה-RL, למשל
opentelemetry-instrumentation-flask.
עלויות
כששולחים נתוני טלמטריה אל Google Cloud, החיוב הוא לפי נפח ההטמעה. החיוב על מדדים מתבצע לפי התמחור של השירות המנוהל של Google Cloud ל-Prometheus, החיוב על יומנים מתבצע לפי התמחור של Cloud Logging והחיוב על עקבות מתבצע לפי התמחור של Cloud Trace.
למידע על העלויות שקשורות להוספה של נתונים של מעקב, יומנים ומדדים של השירות המנוהל של Google Cloud ל-Prometheus, ראו תמחור של Google Cloud Observability.
לבצע אינסטרומנטציה לאפליקציה באמצעות OpenTelemetry
מוסיפים אינסטרומנטציה לקוד של אפליקציית Python RL כדי שהיא תוכל לפלוט מדדים של OpenTelemetry. כדי להוסיף לאפליקציה את האפשרות למדוד את הביצועים שלה:
מאתחלים את 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")יוצרים מכשירים לכל מדד ומתעדים את הערכים שרוצים שהאפליקציה תפיק. מצרפים מוסכמות סמנטיות רלוונטיות בתור מאפיינים.
אפשר להשתמש ברשימה של מוסכמות סמנטיות ואותות חשובים כדי לקבוע אילו מדדים להטמיע באפליקציה.
דוגמה למכשירים למדדים ספציפיים:
# 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 (תצוגה מקדימה). התכונה הזו אוספת נתוני טלמטריה, כמו מדדים ועקבות, ושולחת את הנתונים אל Google Cloud Observability.
כדי להפעיל ולהגדיר את Managed OpenTelemetry ל-GKE, מבצעים את הפעולות הבאות:
מפעילים את Managed OpenTelemetry ל-GKE באשכול שבו האפליקציה פועלת. כדי לעשות זאת, פועלים לפי השלבים במאמר בנושא הפעלת OpenTelemetry מנוהל ל-GKE באשכול.
מוסיפים הערות לפריסת האפליקציה עם משתני סביבה כדי להנחות את 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 עם Managed OpenTelemetry מופעל, המדדים נשלחים ל-Monitoring. המדדים בדרך כלל זמינים בדומיין prometheus.googleapis.com/.
כדי לראות את מדדי רשימת החברים בהתאמה אישית ב-Monitoring:
כדי לראות את מדדי ה-RL בלוח בקרה, אפשר לבצע אחת מהפעולות הבאות:
במסוף Google Cloud , פותחים את Metrics Explorer במסוף Google Cloud :
בשדה 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/
סינון וקיבוץ: אתם יכולים להשתמש במסננים ב-Metrics Explorer כדי להשתמש במוסכמות הסמנטיות שהוספתם כמאפיינים. לדוגמה, ההגדרה הבאה מציינת את משך הלולאה לריצה ולאלגוריתם ספציפיים:
- סינון:
metric.label."rl_run_id" == "run-42" - סינון:
metric.label."rl_algorithm" == "PPO" - Group By:
metric.label."rl_environment_name"כדי להשוות בין הביצועים בסביבות שונות.
- סינון:
צפייה בפרטי ההעברה בכלי Trace
המעקב המבוזר מספק ציר זמן של פעולות ועוזר לכם לנפות באגים בזרימת הביצוע במערכת RL.
במסוף Google Cloud , פותחים את Trace Explorer במסוף Google Cloud :
אפשר להריץ שאילתות ולסנן עקבות. הגדרתם את
"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(מד): ניצול FLOPS של המודל (MFU). מציין את מידת היעילות של השימוש במשאבי מחשוב (כמו GPU או TPU) במהלך האימון. אם ה-MFU נמוך, יכול להיות שהשימוש בתכונות לא מספיק או שיש צווארי בקבוק.
המאמרים הבאים
- מידע נוסף על Managed OpenTelemetry ל-GKE
- איך מכווננים ומגדילים את קנה המידה של למידת חיזוק באמצעות Vertex AI RL ב-GKE
- מידע נוסף על מעקב אחרי מערכות מבוזרות