Questo documento illustra come testare e monitorare la pubblicazione online dei modelli di machine learning (ML) di cui viene eseguito il deployment AI Platform Prediction. Il documento utilizza Locust uno strumento open source per i test di carico.
Il documento è rivolto ai data scientist e agli MLOps engineer che vogliono monitorare il carico di lavoro del servizio, la latenza e l'utilizzo delle risorse dei modelli ML e produzione.
Il documento presuppone che tu abbia una certa esperienza con Google Cloud, TensorFlow, AI Platform Prediction, Cloud Monitoring e blocchi note Jupyter.
Il documento è accompagnato da un repository GitHub che include il codice e una guida all'implementazione per l'implementazione del sistema описанном in questo documento. Le attività vengono incorporate nei blocchi note Jupyter.
Costi
I notebook con cui lavori in questo documento utilizzano i seguenti componenti fatturabili di Google Cloud:
- Blocchi note gestiti dall'utente di Vertex AI Workbench
- AI Platform Prediction
- Cloud Storage
- Cloud Monitoring
- Google Kubernetes Engine (GKE)
Per generare una stima dei costi basata sull'utilizzo previsto, utilizza Calcolatore prezzi.
Prima di iniziare
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
Panoramica dell'architettura
Il seguente diagramma mostra l'architettura di sistema per il deployment del modello ML per la previsione online, l'esecuzione del test di carico e la raccolta e l'analisi delle metriche per le prestazioni di pubblicazione del modello ML.
Il diagramma mostra il seguente flusso:
- Il modello addestrato potrebbe trovarsi Cloud Storage: per Ad esempio, un file TensorFlow SavedModel o scikit-learn joblib. In alternativa, potrebbe essere incorporato in un container di pubblicazione personalizzato in Container Registry, ad esempio TorchServe per la pubblicazione di modelli PyTorch.
- Viene eseguito il deployment del modello AI Platform Prediction come API REST. AI Platform Prediction è un servizio completamente gestito del modello che supporta diversi tipi di macchina, supporta scalabilità automatica in base all'utilizzo delle risorse e supporta vari Acceleratori GPU.
- Locust viene utilizzata per implementare un'attività di test (ovvero il comportamento degli utenti). it chiama il modello ML di cui è stato eseguito il deployment AI Platform Prediction ed esecuzione su larga scala Google Kubernetes Engine (GKE) In questo modo vengono simulate molte chiamate utente simultanee per il test di carico del servizio di previsione del modello. Puoi monitorare l'avanzamento dei test utilizzando Interfaccia web di Locust.
- Statistiche di test dei log delle locuste su Cloud Logging. Le voci di log create dal test Locust vengono utilizzate per definire un insieme di metriche basate su log in Cloud Monitoring. Queste metriche completano lo standard Metriche di AI Platform Prediction.
- Sia le metriche della piattaforma AI sia le metriche personalizzate di Locust sono disponibili per la visualizzazione in una dashboard di Cloud Monitoring in tempo reale. Al termine del test, le metriche vengono anche raccolte tramite programmazione in modo da poterle analizzare e visualizzare nei notebook gestiti dall'utente di Vertex AI Workbench.
I blocchi note Jupyter per questo scenario
Tutte le attività per la preparazione e il deployment del modello, l'esecuzione del test della locusta, e la raccolta e l'analisi dei risultati dei test sono codificate nel seguente schema blocchi note. Per eseguire le attività, esegui la sequenza di celle in ogni blocco note.
01-prepare-and-deploy.ipynb
. Esegui questo notebook per preparare un SavedModel di TensorFlow per il servizio e per eseguire il deployment del modello in AI Platform Prediction.02-perf-testing.ipynb
Esegui questo blocco note per creare metriche basate su log in Cloud Monitoring per il test della locusta e di eseguire il deployment GKE ed eseguirlo.03-analyze-results.ipynb
. Esegui questo notebook per raccogliere e analizzare i risultati del test di carico Locust dalle metriche standard di AI Platform create da Cloud Monitoring e dalle metriche Locust personalizzate.
Inizializzazione dell'ambiente
Come descritto nel
README.md
file del repository GitHub associato, devi eseguire i seguenti
passaggi per preparare l'ambiente per l'esecuzione dei notebook:
- Nel tuo progetto Google Cloud, crea un bucket Cloud Storage, obbligatorio per archiviare il modello addestrato e la configurazione del test Locust. Prendi nota del nome utilizzato per il bucket, perché ti servirà in seguito.
- Crea un'area di lavoro Cloud Monitoring nel tuo progetto.
- Crea un cluster Google Kubernetes Engine con le CPU richieste. Il pool di nodi deve avere accesso alle API Cloud.
- Crea un'istanza di notebook gestita dall'utente di Vertex AI Workbench che utilizza TensorFlow 2. Per questo tutorial non sono necessarie GPU perché non addestra il modello. Le GPU possono essere utili in altri scenari, in particolare per accelerare l'addestramento dei modelli.
Apertura di JupyterLab
Per svolgere le attività per lo scenario, devi aprire l'ambiente JupyterLab e recuperare i notebook.
Nella console Google Cloud, vai alla pagina Notebook.
Nella scheda Blocchi note gestiti dall'utente, fai clic su Apri JupyterLab accanto all'ambiente di notebook che hai creato.
Viene aperto l'ambiente JupyterLab nel browser.
Per avviare una scheda del terminale, fai clic sull'icona Terminale nella scheda Avvio app.
Nel terminale, clona
mlops-on-gcp
Repository GitHub:git clone https://github.com/GoogleCloudPlatform/mlops-on-gcp.git
Al termine del comando, vedrai la cartella
mlops-on-gcp
nel browser di file. In questa cartella, vedrai i blocchi note che utilizzi documento.
Configurazione delle impostazioni del blocco note in corso
In questa sezione, imposti le variabili nei notebook con valori specifici per il tuo contesto e prepari l'ambiente per eseguire il codice per lo scenario.
- Vai alla directory
model_serving/caip-load-testing
. - Per ciascuno dei tre notebook, svolgi le seguenti operazioni:
- Apri il notebook.
- Esegui le celle in Configura le impostazioni dell'ambiente Google Cloud.
Le seguenti sezioni evidenziano le parti principali del processo e spiegano gli aspetti del design e del codice.
Pubblicazione del modello per la previsione online
Il modello ML utilizzato in questo documento utilizza il preaddestrato modello di classificazione delle immagini ResNet V2 101 di TensorFlow Hub. Tuttavia, puoi adattare i pattern e le tecniche di progettazione di sistema di questo documento ad altri domini e ad altri tipi di modelli.
Il codice per la preparazione e l'erogazione del modello ResNet 101 si trova nel
notebook 01-prepare-and-deploy.ipynb
. Esegui le celle nel notebook per svolgere le seguenti attività:
- Scarica ed esegui il modello ResNet da TensorFlow Hub.
- Creare firme di servizio per il modello.
- Esporta il modello come SavedModel.
- Eseguire il deployment del SavedModel in AI Platform Prediction.
- Convalida il modello di cui è stato eseguito il deployment.
Le sezioni successive di questo documento forniscono dettagli sulla preparazione del modello ResNet e sul suo dispiegamento.
prepara il modello ResNet per il deployment
Il modello ResNet di TensorFlow Hub non ha firme per la pubblicazione perché è ottimizzato per la ricomposizione e il perfezionamento. Di conseguenza, devi creare la pubblicazione di firme per il modello in modo che possa esserlo online per le previsioni.
Inoltre, per pubblicare il modello, ti consigliamo di incorporare la logica di creazione delle funzionalità nell'interfaccia di pubblicazione. In questo modo, affinità tra la pre-elaborazione e la distribuzione del modello, anziché sull'applicazione client per pre-elaborare i dati nel formato richiesto. Devi includono anche la post-elaborazione nell'interfaccia di distribuzione, ad esempio la conversione ID classe a un'etichetta di classe.
Per rendere il modello ResNet disponibile, devi implementare le firme di pubblicazione che descrivono i metodi di inferenza del modello. Di conseguenza, il codice del blocco note aggiunge due firme:
- La firma predefinita. Questa firma espone il valore predefinito
predict
del modello ResNet V2 101; il metodo predefinito non prevede o dalla logica di post-elaborazione. - Firma di pre-elaborazione e post-elaborazione. Gli input previsti per questa interfaccia richiede una pre-elaborazione relativamente complessa, la codifica, il ridimensionamento e la normalizzazione dell'immagine. Pertanto, il modello esposto anche una firma alternativa che incorpora la logica di pre-elaborazione e post-elaborazione. Questa firma accetta immagini non elaborate e restituisce l'elenco delle etichette di classe classificate e le probabilità associate.
Le firme vengono create in una classe di modulo personalizzata. La classe è derivata dalla
tf.Module
classe di base che incapsula il modello ResNet. La classe personalizzata estende la classe di base con un metodo che implementa la logica di pre-elaborazione delle immagini e di post-elaborazione dell'output. Il metodo predefinito del modulo personalizzato viene mappato al metodo predefinito del modello ResNet di base per mantenere l'interfaccia analoga. Il
modulo personalizzato viene esportato come SavedModel che include il modello originale, la
logica di preelaborazione e due firme di pubblicazione.
L'implementazione della classe del modulo personalizzato è illustrata nel codice che segue snippet:
LABELS_KEY = 'labels'
PROBABILITIES_KEY = 'probabilities'
NUM_LABELS = 5
class ServingModule(tf.Module):
"""
A custom tf.Module that adds image preprocessing and output post processing to
a base TF 2 image classification model from TensorFlow Hub.
"""
def __init__(self, base_model, input_size, output_labels):
super(ServingModule, self).__init__()
self._model = base_model
self._input_size = input_size
self._output_labels = tf.constant(output_labels, dtype=tf.string)
def _decode_and_scale(self, raw_image):
"""
Decodes, crops, and resizes a single raw image.
"""
image = tf.image.decode_image(raw_image, dtype=tf.dtypes.uint8, expand_animations=False)
image_shape = tf.shape(image)
image_height = image_shape[0]
image_width = image_shape[1]
crop_size = tf.minimum(image_height, image_width)
offset_height = ((image_height - crop_size) + 1) // 2
offset_width = ((image_width - crop_size) + 1) // 2
image = tf.image.crop_to_bounding_box(image, offset_height, offset_width, crop_size, crop_size)
image = tf.image.resize(image, [self._input_size, self._input_size])
image = tf.cast(image, tf.uint8)
return image
def _preprocess(self, raw_inputs):
"""
Preprocesses raw inputs as sent by the client.
"""
# A mitigation for https://github.com/tensorflow/tensorflow/issues/28007
with tf.device('/cpu:0'):
images = tf.map_fn(self._decode_and_scale, raw_inputs, dtype=tf.uint8)
images = tf.image.convert_image_dtype(images, tf.float32)
return images
def _postprocess(self, model_outputs):
"""
Postprocess outputs returned by the base model.
"""
probabilities = tf.nn.softmax(model_outputs)
indices = tf.argsort(probabilities, axis=1, direction='DESCENDING')
return {
LABELS_KEY: tf.gather(self._output_labels, indices, axis=-1)[:,:NUM_LABELS],
PROBABILITIES_KEY: tf.sort(probabilities, direction='DESCENDING')[:,:NUM_LABELS]
}
@tf.function(input_signature=[tf.TensorSpec([None, 224, 224, 3], tf.float32)])
def __call__(self, x):
"""
A pass-through to the base model.
"""
return self._model(x)
@tf.function(input_signature=[tf.TensorSpec([None], tf.string)])
def predict_labels(self, raw_images):
"""
Preprocesses inputs, calls the base model
and postprocess outputs from the base model.
"""
# Call the preprocessing handler
images = self._preprocess(raw_images)
# Call the base model
logits = self._model(images)
# Call the postprocessing handler
outputs = self._postprocess(logits)
return outputs
serving_module = ServingModule(model, 224, imagenet_labels)
Il seguente snippet di codice mostra come il modello viene esportato come SavedModel con le firme per la pubblicazione definite in precedenza:
...
default_signature = serving_module.__call__.get_concrete_function()
preprocess_signature = serving_module.predict_labels.get_concrete_function()
signatures = {
'serving_default': default_signature,
'serving_preprocess': preprocess_signature
}
tf.saved_model.save(serving_module, model_path, signatures=signatures)
Esegui il deployment del modello in AI Platform Prediction
Quando il modello viene esportato come SavedModel, vengono eseguite le seguenti attività eseguita:
- Il modello viene caricato su Cloud Storage.
- Viene creato un oggetto modello in AI Platform Prediction.
- Viene creata una versione del modello per il SavedModel.
Il seguente snippet di codice del blocco note mostra i comandi che eseguono queste attività.
gcloud storage cp {model_path} {GCS_MODEL_LOCATION} --recursive
gcloud ai-platform models create {MODEL_NAME} \
--project {PROJECT_ID} \
--regions {REGION}
MACHINE_TYPE='n1-standard-8'
ACCELERATOR='count=1,type=nvidia-tesla-p4'
gcloud beta ai-platform versions create {MODEL_VERSION} \
--model={MODEL_NAME} \
--origin={GCS_MODEL_LOCATION} \
--runtime-version=2.1 \
--framework=TENSORFLOW \
--python-version=3.7 \
--machine-type={MACHINE_TYPE} \
--accelerator={ACCELERATOR} \
--project={PROJECT_ID}
Il comando crea un tipo di macchina n1-standard-8
per il servizio di previsione del modello insieme a un acceleratore GPU nvidia-tesla-p4
.
Dopo aver eseguito le celle del blocco note che contengono questi comandi, puoi verificare che il deployment della versione del modello viene eseguito visualizzandola nella pagina Modelli AI Platform del Console Google Cloud. L'output è simile al seguente:
Creazione di metriche di Cloud Monitoring
Al termine della configurazione del modello per la pubblicazione, puoi configurare le metriche
per il monitoraggio delle prestazioni
della pubblicazione. Il codice per configurare le metriche è
02-perf-testing.ipynb
un blocco note personalizzato.
La prima parte del notebook
02-perf-testing.ipynb
crea metriche personalizzate basate su log in Cloud Monitoring utilizzando il
SDK Python Cloud Logging.
Le metriche si basano sulle voci di log generate dall'attività Locust.
La
log_stats
scrive le voci di log in un log di Cloud Logging denominato locust
.
Ogni voce di log include un insieme di coppie chiave/valore in formato JSON, come elencato in: la tabella seguente. Le metriche sono basate sul sottoinsieme di chiavi del log .
Chiave | Descrizione del valore | Utilizzo |
---|---|---|
test_id
|
L'ID di un test | Filtro degli attributi |
model |
Nome del modello di AI Platform Prediction | |
model_version |
La versione del modello AI Platform Prediction | |
latency
|
Il tempo di risposta al 95° percentile, calcolato su un intervallo di 10 secondi finestra scorrevole | Valori metriche |
num_requests |
Il numero totale di richieste dall'inizio del test | |
num_failures |
Il numero totale di errori dall'avvio del test | |
user_count |
Il numero di utenti simulati | |
rps |
Le richieste al secondo |
Il seguente snippet di codice mostra la funzione create_locust_metric
nel
un blocco note che crea una metrica personalizzata
basata su log.
def create_locust_metric(
metric_name:str,
log_path:str,
value_field:str,
bucket_bounds:List[int]):
metric_path = logging_client.metric_path(PROJECT_ID, metric_name)
log_entry_filter = 'resource.type=global AND logName={}'.format(log_path)
metric_descriptor = {
'metric_kind': 'DELTA',
'value_type': 'DISTRIBUTION',
'labels': [{'key': 'test_id', 'value_type': 'STRING'},
{'key': 'signature', 'value_type': 'STRING'}]}
bucket_options = {
'explicit_buckets': {'bounds': bucket_bounds}}
value_extractor = 'EXTRACT(jsonPayload.{})'.format(value_field)
label_extractors = {
'test_id': 'EXTRACT(jsonPayload.test_id)',
'signature': 'EXTRACT(jsonPayload.signature)'}
metric = logging_v2.types.LogMetric(
name=metric_name,
filter=log_entry_filter,
value_extractor=value_extractor,
bucket_options=bucket_options,
label_extractors=label_extractors,
metric_descriptor=metric_descriptor,
)
try:
logging_client.get_log_metric(metric_path)
print('Metric: {} already exists'.format(metric_path))
except:
logging_client.create_log_metric(parent, metric)
print('Created metric {}'.format(metric_path))
Il seguente snippet di codice mostra come viene invocato il metodo create_locust_metric
nel notebook per creare le quattro metriche Locust personalizzate mostrate nella tabella precedente.
# user count metric
metric_name = 'locust_users'
value_field = 'user_count'
bucket_bounds = [1, 16, 32, 64, 128]
create_locust_metric(metric_name, log_path, value_field, bucket_bounds)
# latency metric
metric_name = 'locust_latency'
value_field = 'latency'
bucket_bounds = [1, 50, 100, 200, 500]
create_locust_metric(metric_name, log_path, value_field, bucket_bounds)
# failure count metric
metric_name = 'num_failures'
value_field = 'num_failures'
bucket_bounds = [1, 1000]
create_locust_metric(metric_name, log_path, value_field, bucket_bounds)
# request count metric
metric_name = 'num_requests'
value_field = 'num_requests'
bucket_bounds = [1, 1000]
create_locust_metric(metric_name, log_path, value_field, bucket_bounds)
Il notebook crea una dashboard di Cloud Monitoring personalizzata denominata AI Platform Prediction and Locust. La dashboard combina le metriche standard di AI Platform Prediction e le metriche personalizzate in base ai log di Locust.
Per ulteriori informazioni, consulta API Cloud Logging documentazione.
Questa dashboard e i relativi grafici possono essere
creati manualmente.
Tuttavia, il blocco note fornisce un modo programmatico per crearlo utilizzando
monitoring-template.json
modello JSON. Il codice utilizza la classe
DashboardsServiceClient
per caricare il modello JSON e creare la dashboard in Cloud Monitoring, come mostrato nello snippet di codice seguente:
parent = 'projects/{}'.format(PROJECT_ID)
dashboard_template_file = 'monitoring-template.json'
with open(dashboard_template_file) as f:
dashboard_template = json.load(f)
dashboard_proto = Dashboard()
dashboard_proto = ParseDict(dashboard_template, dashboard_proto)
dashboard = dashboard_service_client.create_dashboard(parent, dashboard_proto)
Una volta creata, la dashboard viene visualizzata nell'elenco di alle dashboard di Cloud Monitoring Console Google Cloud:
Puoi fare clic sulla dashboard per aprirla e visualizzare i grafici. Ogni grafico viene visualizzato una metrica da AI Platform Prediction o dai log di Locust, come mostrato negli screenshot seguenti.
Eseguire il deployment del test Locust nel cluster GKE
Prima di eseguire il deployment del sistema Locust in GKE,
per creare
Immagine container Docker
che contiene la logica di test incorporata nel file task.py
. L'immagine è
derivato dal
baseline locust.io
immagine
e viene utilizzato per i pod master e worker.
La logica per la creazione e il deployment è indicata nel blocco note in 3. Esegui il deployment di Locust in un cluster GKE. L'immagine viene creata utilizzando il seguente codice:
image_uri = 'gcr.io/{}/locust'.format(PROJECT_ID)
!gcloud builds submit --tag {image_uri} locust/locust-image
Il processo di deployment descritto nel notebook è stato definito utilizzando Kustomize. I manifest di deployment di Locust Kustomize definiscono i seguenti file che definiscono i componenti:
locust-master
Questo file definisce un deployment che ospita un'interfaccia web da cui inizi il test e visualizzare le statistiche in tempo reale.locust-worker
. Questo file definisce un deployment che esegue un'attività per eseguire il test di carico del servizio di previsione del modello di ML. Di solito, vengono creati più worker per simulare effetto di più utenti simultanei che effettuano chiamate alla tua previsione API di Google Cloud.locust-worker-service
Questo file definisce un servizio che accede all'interfaccia web inlocust-master
tramite un bilanciatore del carico HTTP.
Devi aggiornare il manifest predefinito prima del deployment del cluster. Il manifest predefinito è costituito dai file kustomization.yaml
e patch.yaml
. Devi apportare modifiche in entrambi i file.
Nel file kustomization.yaml
, procedi nel seguente modo:
- Imposta il nome dell'immagine personalizzata della locusta. Imposta il campo
newName
nelimages
al nome dell'immagine personalizzata che hai creato in precedenza. - (Facoltativo) Imposta il numero di pod worker. La configurazione predefinita consente di eseguire il deployment di 32 pod worker. Per modificare il numero, modifica il campo
count
nella sezionereplicas
. Assicurati che i tuoi cluster GKE ha un numero sufficiente di CPU per i worker Locust. - Imposta il bucket Cloud Storage per la configurazione di test e
dei file di payload. Nella sezione
configMapGenerator
, assicurati che il parametro i seguenti valori:LOCUST_TEST_BUCKET
. Impostalo sul nome dell'istanza di Cloud Storage che hai creato in precedenza.LOCUST_TEST_CONFIG
. Imposta il nome del file di configurazione del test. Nel file YAML il file è impostato sutest-config.json
, ma puoi modificare questa impostazione se vuoi usare un altro nome.LOCUST_TEST_PAYLOAD
. Imposta questo valore sul nome del file del payload di test. Nel file YAML, questo valore è impostato sutest-payload.json
, ma puoi modificarlo se vuoi utilizzare un nome diverso.
Nel file patch.yaml
:
- Se vuoi, modifica il pool di nodi che ospita il master e i worker di Locust. Se esegui il deployment del carico di lavoro Locust su un pool di nodi diverso da
default-pool
, trova la sezionematchExpressions
, quindi sottovalues
, aggiorna il nome del pool di nodi che verrà assegnato al carico di lavoro Locust in cui è stato eseguito il deployment.
Dopo aver apportato queste modifiche, puoi creare le tue personalizzazioni nei manifest di Kustomize e applicare il deployment di Locust (locust-master
,
locust-worker
e locust-master-service
) al cluster GKE. Il seguente comando nel blocco note esegue queste attività:
!kustomize build locust/manifests | kubectl apply -f -
Puoi controllare i carichi di lavoro di cui è stato eseguito il deployment Console Google Cloud. L'output è simile al seguente:
Implementazione del test di carico Locust
Il compito di test di Locust è chiamare il modello di cui è stato eseguito il deployment in AI Platform Prediction.
Questa attività viene implementata nel
AIPPClient
nel
task.py
modulo nella cartella /locust/locust-image/
. Il seguente snippet di codice mostra l'implementazione della classe.
class AIPPClient(object):
"""
A convenience wrapper around AI Platform Prediction REST API.
"""
def __init__(self, service_endpoint):
logging.info(
"Setting the AI Platform Prediction service endpoint: {}".format(service_endpoint))
credentials, _ = google.auth.default()
self._authed_session = AuthorizedSession(credentials)
self._service_endpoint = service_endpoint
def predict(self, project_id, model, version, signature, instances):
"""
Invokes the predict method on the specified signature.
"""
url = '{}/v1/projects/{}/models/{}/versions/{}:predict'.format(
self._service_endpoint, project_id, model, version)
request_body = {
'signature_name': signature,
'instances': instances
}
response = self._authed_session.post(url, data=json.dumps(request_body))
return response
La classe AIPPUser
nel file task.py
eredita dalla classe locust.User
per simulare il comportamento dell'utente che chiama il modello di Previsione di AI Platform. Questo comportamento è implementato nel metodo predict_task
. Il metodo on_start
della classe AIPPUser
scarica i seguenti file da un bucket Cloud Storage specificato nella variabile LOCUST_TEST_BUCKET
nel file task.py
:
test-config.json
. Questo file JSON include quanto segue: configurazioni del test:test_id
,project_id
,model
eversion
.test-payload.json
. Questo file JSON include le istanze di dati nel formato previsto da AI Platform Prediction, insieme alla firma target.
Il codice per la preparazione dei dati di test e la configurazione di test è incluso nel
02-perf-testing.ipynb
blocco note in 4. Configura un test Locust.
Le configurazioni di test e le istanze di dati vengono utilizzate come parametri
predict
nella classe AIPPClient
per testare il modello target utilizzando il
i dati di test richiesti. AIPPUser
Simula un tempo di attesa
di 1-2 secondi tra le chiamate di un singolo utente.
Eseguire il test Locust
Dopo aver eseguito le celle del blocco note per eseguire il deployment del carico di lavoro Locust
cluster GKE e, dopo aver creato e caricato
test-config.json
e test-payload.json
in Cloud Storage,
può avviare, arrestare e configurare un nuovo test di carico della locusta utilizzando la sua
interfaccia web.
Il codice nel blocco note recupera l'URL del bilanciatore del carico esterno che
espone l'interfaccia web utilizzando il seguente comando:
%%bash
IP_ADDRESS=$(kubectl get service locust-master | awk -v col=4 'FNR==2{print $col}')
echo http://$IP_ADDRESS:8089
Per eseguire il test:
- In un browser, inserisci l'URL recuperato.
Per simulare il carico di lavoro di test utilizzando configurazioni diverse, inserisci nell'interfaccia di Locust, simile alla seguente:
Lo screenshot precedente mostra i seguenti valori di configurazione:
- Numero totale di utenti da simulare:
150
- Frequenza di schiusa:
1
- Host:
http://ml.googleapis.com
- Numero di utenti da aumentare per passaggio:
10
- Durata del passaggio:
2m
- Numero totale di utenti da simulare:
Durante l'esecuzione del test, puoi monitorarlo esaminando i grafici di Locust. Gli screenshot seguenti mostrano come vengono visualizzati i valori.
Un grafico mostra il numero totale di richieste al secondo:
Un altro grafico mostra il tempo di risposta in millisecondi:
Come accennato in precedenza, queste statistiche vengono registrate anche in Cloud Logging, in modo da poter creare metriche personalizzate basate sui log di Cloud Monitoring.
Raccolta e analisi dei risultati del test
L'attività successiva è raccogliere e analizzare le metriche di Cloud Monitoring
vengono calcolate dai log dei risultati come
oggetto pandas DataFrame
in modo da poter visualizzare e analizzare i risultati nel blocco note. Il codice per eseguire questa operazione si trova nel notebook 03-analyze-results.ipynb
.
Il codice utilizza il parametro
SDK Python per le query di Cloud Monitoring
per filtrare e recuperare i valori delle metriche, dati che vengono passati nel
project_id
, test_id
, start_time
, end_time
, model
, model_version
e
Parametri log_name
.
Il seguente snippet di codice mostra i metodi che recuperano Le metriche di AI Platform Prediction e i log di Locust personalizzati metriche di valutazione.
import pandas as pd
from google.cloud.monitoring_v3.query import Query
def _get_aipp_metric(metric_type: str, labels: List[str]=[], metric_name=None)-> pd.DataFrame:
"""
Retrieves a specified AIPP metric.
"""
query = Query(client, project_id, metric_type=metric_type)
query = query.select_interval(end_time, start_time)
query = query.select_resources(model_id=model)
query = query.select_resources(version_id=model_version)
if metric_name:
labels = ['metric'] + labels
df = query.as_dataframe(labels=labels)
if not df.empty:
if metric_name:
df.columns.set_levels([metric_name], level=0, inplace=True)
df = df.set_index(df.index.round('T'))
return df
def _get_locust_metric(metric_type: str, labels: List[str]=[],
metric_name=None)-> pd.DataFrame:
"""
Retrieves a specified custom logs-based metric.
"""
query = Query(client, project_id, metric_type=metric_type)
query = query.select_interval(end_time, start_time)
query = query.select_metrics(log=log_name)
query = query.select_metrics(test_id=test_id)
if metric_name:
labels = ['metric'] + labels
df = query.as_dataframe(labels=labels)
if not df.empty:
if metric_name:
df.columns.set_levels([metric_name], level=0, inplace=True)
df = df.apply(lambda row: [metric.mean for metric in row])
df = df.set_index(df.index.round('T'))
return df
I dati delle metriche vengono recuperati come oggetto DataFrame
di pandas per ogni metrica.
I singoli frame di dati vengono poi uniti in un unico oggetto DataFrame
. L'oggetto DataFrame
finale con i risultati uniti sarà simile al seguente nel tuo notebook:
L'oggetto DataFrame
recuperato utilizza
l'indicizzazione gerarchica
per i nomi delle colonne. Il motivo è che alcune metriche contengono più serie temporali.
Ad esempio, la metrica GPU duty_cycle
include una serie temporale di misurazioni per ogni GPU utilizzata nel deployment, indicata come replica_id
. Il livello superiore
dell'indice di colonna mostra il nome di una singola metrica. Il secondo livello è
un ID replica. Il terzo livello mostra la firma di un modello. Tutte le metriche sono
allineate sulla stessa sequenza temporale.
I seguenti grafici mostrano l'utilizzo della GPU, l'utilizzo della CPU e la latenza come appaiono nel notebook.
Utilizzo GPU:
Utilizzo CPU:
Latenza:
I grafici mostrano il seguente comportamento e sequenza:
- Con l'aumento del carico di lavoro (numero di utenti), l'utilizzo di CPU e GPU aumentano. Di conseguenza, la latenza aumenta e la differenza la latenza del modello e la latenza totale aumentano fino a raggiungere il picco intorno alle 20:40.
- Alle 20:40, l'utilizzo della GPU raggiunge il 100%, mentre il grafico della CPU mostra che
raggiunge 4 CPU. In questo test, il sample utilizza una macchina
n1-standard-8
con 8 CPU. Pertanto, l'utilizzo della CPU raggiunge il 50%. - A questo punto, la scalabilità automatica aggiunge capacità: viene aggiunto un nuovo nodo di pubblicazione con una replica GPU aggiuntiva. L'utilizzo della prima replica della GPU diminuisce e l'utilizzo della seconda replica della GPU aumenta.
- La latenza diminuisce quando la nuova replica inizia a fornire le previsioni, convergendo a circa 200 millisecondi.
- L'utilizzo della CPU converge di circa il 250% per ogni replica, ovvero
Utilizzando 2,5 CPU su 8. Questo valore indica che puoi utilizzare una macchina
n1-standard-4
anziché unan1-standard-8
.
Pulizia
Per evitare che a Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo documento, elimina il progetto che contiene le risorse, o mantenere il progetto ed eliminare le singole risorse.
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
Se vuoi mantenere il progetto Google Cloud, ma eliminare le risorse che hai creato, elimina il cluster Google Kubernetes Engine e il modello di AI Platform di cui è stato eseguito il deployment.
Passaggi successivi
- Scopri di più su MLOps e sulle pipeline di distribuzione continua e automazione nel machine learning.
- Scopri di più sull'architettura per MLOps utilizzando TFX, Kubeflow Pipelines e Cloud Build.
- Per altre architetture di riferimento, diagrammi e best practice, visita il Centro architetture di Google Cloud.