Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Distributed accelerator for cloud storage (DACS) fornisce un client Python nativo per la lettura dei dati Azure Blob attraverso la cache distribuita.
Completa Inizia con l'acceleratore distribuito per lo storage cloud su AKS prima di utilizzare questo articolo.
Installa il client Python nativo
Installa il pacchetto da PyPI nell'immagine del carico di lavoro:
python3 -m pip install "dacs-client==0.1.0"
Se stai aggiornando un carico di lavoro esistente, aggiorna il pin del pacchetto nella definizione della build dell'immagine, ricostruisci e spingi l'immagine, e ridistribuisci i pod di carico di lavoro con l'immagine aggiornata. Installare il pacchetto localmente non aggiorna i container in esecuzione. Per i comandi di build e push dell'immagine, vedi Aggiungi il client a un'immagine del carico di lavoro.
Il pacchetto richiede Python 3.8 o più recente e un ambiente Linux con glibc 2.35 o versioni successive. Fornisce wheel autonome manylinux_2_35 per x86-64 e arm64, inclusa la libreria nativa e le sue dipendenze da librerie condivise. La azure-identity dipendenza si installa automaticamente.
Il quickstart utilizza Python 3.12 su python:3.12-slim-bookworm con nodi x86-64.
Verifica l'installazione all'interno del container del workload:
python3 -c "import importlib.metadata; import py_dacs_client; print(importlib.metadata.version('dacs-client'))"
Il comando deve stampare 0.1.0. Il nome della distribuzione è dacs-client, ma il nome di importazione Python è py_dacs_client.
Configurare il client
Imposta entrambe le variabili di scoperta della cache su ogni pod che utilizza un acceleratore distribuito per lo storage cloud:
env:
- name: CACHE_DISCOVERY_URL
value: <discovery-service-hostname>
- name: CACHE_SERVER_PORT
value: "9065"
Importante
Entrambe le variabili sono necessarie. Se manca uno dei due, il client registra Cache not configured. Working in Remote Blob mode only. nel log e accede direttamente ad Archiviazione BLOB di Azure. L'operazione può avere successo senza utilizzare la cache.
Usa il nome host del servizio di scoperta per la tua risorsa e namespace della cache, ad esempio, cache-sample-discovery.<namespace>.svc.cluster.local, con porta 9065.
Configura l'autenticazione Blob prima di creare il client. Il seguente esempio utilizza l'identità gestita di AKS kubelet tramite l'Instance Metadata Service (IMDS) del nodo, non l'identità federata del carico di lavoro AKS. Imposta AZURE_CLIENT_ID sull'ID client dell'identità kubelet:
env:
- name: AZURE_CLIENT_ID
value: <kubelet-identity-client-id>
- name: MSI_ENDPOINT
value: "http://169.254.169.254/metadata/identity/oauth2/token"
- name: MSI_SECRET
value: "required-nonempty-value"
Il Pod deve essere in grado di raggiungere IMDS. Per questa configurazione client-nativo, MSI_SECRET è un marcatore di compatibilità non vuoto richiesto, non un vero segreto o credenziali. Non mettere una credenziale in quel valore. Queste impostazioni sono specifiche dell'integrazione; non copiarle nella configurazione di autenticazione di Run:ai.
Per l'inferenza di sola lettura, concedere all'identità kubelet il ruolo Storage Blob Data Reader con ambito al contenitore del modello. Vedi Concedere l'accesso in lettura ai dati del modello. Usa Storage Blob Data Contributor solo quando l'applicazione deve scrivere dati. Non è necessario il permesso di scrittura di un uploader separato per le letture in fase di esecuzione.
Usa questo formato canonico di percorso:
az://<account>.blob.core.windows.net/<container>/<path>
Il livello nativo legge la configurazione quando viene creato il primo client in un processo. Configura l'ambiente e le impostazioni del client prima di creare quel client. I client successivi non cambiano la configurazione nativa già in vigo.
Comprendere i cache miss e le letture concorrenti
Quando più client richiedono contemporaneamente gli stessi dati mancanti, ogni client può recuperare autonomamente i dati da Archiviazione BLOB di Azure. La popolazione coordinata del cold cache non è disponibile in questa anteprima.
La popolazione della cache è asincrona. Una lettura può terminare prima che i suoi dati siano disponibili dalla cache, quindi due letture immediate possono entrambe risultare cache miss anche se i byte restituiti corrispondono.
Prima di eventi di scalabilità sincronizzata di grandi dimensioni, precaricare i BLOB di modello selezionati tramite DACS prima di iniziare le repliche di inferenza. Consultare Prelettura dei dati del modello prima della distribuzione per un pod di riscaldamento dedicato, i comandi di lettura e la verifica dell'implementazione.
Una lettura di successo può derivare dal fallback di Archiviazione BLOB di Azure. Per verificare che le letture utilizzino DACS:
- Prima di leggere, registrare
cache_server_request_counter{request_type="Download",status="Success"}, sommato su tutti i pod del server cache per la risorsa cache. I valori delle etichette sono sensibili a maiuscole e minuscole. - Leggi ripetutamente lo stesso intervallo di blob con un ritardo tra una lettura e l'altra. Il quickstart utilizza cinque letture distanziate di un secondo; questa sequenza non garantisce che il popolamento sia completato. Conferma che il conteggio dei download riusciti dal server aumenti e che il client segnali gli hit della cache. Controlla il conteggio dei byte restituiti e i checksum per l'integrità dei dati; il tempo più veloce da solo non dimostra l'uso della cache.
- Correlare le metriche client e server con la telemetria di BLOB di Azure per distinguere il traffico della cache dalle letture di origine e dal fallback.
Per i comandi per raccogliere le metriche del client e i contatori del server, consulta Verifica il percorso delle richieste DACS.
Usa il client nativo
Il client nativo fornisce metodi asincroni e controparti sincrone. Legge in buffer nativi preallocati. Impostare MODEL_PATH sul percorso canonico az:// di una partizione del modello esistente prima di eseguire il seguente esempio, che legge fino ai primi 4 MiB:
import asyncio
import os
from py_dacs_client.dacs_client import DACSCacheClient
from py_dacs_client.dacs_utils import BoundedBufferManager
async def main():
path = os.environ["MODEL_PATH"]
client = DACSCacheClient()
buffers = BoundedBufferManager(max_memory_limit=64 * 1024 * 1024)
try:
size = min(await client.get_file_size(path), 4 * 1024 * 1024)
if size == 0:
print("read 0 bytes")
return
buffer = await buffers.acquire_buffer(size)
try:
bytes_read = await client.read_blob(path, buffer, size, 0)
print(f"read {bytes_read} bytes")
finally:
await buffers.release_buffer(buffer)
finally:
await client.shutdown()
asyncio.run(main())
I metodi di lettura più comuni includono:
| Metodo asincrono | Metodo sincrono | Description |
|---|---|---|
get_file_size(path) |
get_file_size_sync(path) |
Ottieni la dimensione del blob in byte. |
get_file_stat(path) |
get_file_stat_sync(path) |
Ottenere i metadati del file del modello. |
read_blob(path, buffer, size, offset) |
read_blob_sync(...) |
Leggere un intervallo di byte in un buffer preallocato. |
list_dir(path) |
list_dir_sync(path) |
Elencare le voci della directory. |
get_file_handle(path, flags) |
get_file_handle_sync(...) |
Apri un handle riutilizzabile. |
release_file_handle(handle) |
release_file_handle_sync(handle) |
Chiudi un handle riutilizzabile. |
shutdown() |
shutdown_sync() |
Rilascia le connessioni ed emetti le metriche finali. |
Il metodo asincrono list_dir(path) restituisce un iteratore; usa async for per consumare le voci della directory.
Usa le letture a intervallo per i formati di modello che non richiedono ogni byte. L'acceleratore distribuito per l'archiviazione cloud memorizza solo i blocchi che coprono gli intervalli richiesti.
Ottimizza le prestazioni di lettura
Ottimizzare congiuntamente la concorrenza di lettura dell'applicazione e la dimensione dell'intervallo di byte richiesto. Le impostazioni migliori dipendono dal modello di accesso, dai limiti di CPU e memoria del pod, dalla larghezza di banda di rete del client e del nodo di cache e dal fatto che le letture raggiungano la cache o eseguano il fallback in Archiviazione BLOB.
Usa i valori in questa sezione come punti di partenza per i benchmark del carico di lavoro, non come raccomandazioni di prestazioni garantite. Misura il loro effetto con il tuo carico di lavoro prima di distribuire i cambiamenti.
Regolare la concorrenza
La concorrenza è il numero di letture che l'applicazione mantiene in esecuzione. Un ciclo che attende ogni chiamata read_blob prima di iniziare la successiva è sequenziale, anche quando utilizza l'API asincrona.
- Esegui letture indipendenti di intervallo di byte o di BLOB contemporaneamente. Limita il numero di letture attive con un
asyncio.Semaphoreo un numero fisso di task di lavoro. Non creare un compito per ogni intervallo di un grande dataset contemporaneamente. - Inizia con un piccolo limite, come quattro letture concorrenti, e confrontalo con otto e sedici. Aumentare la concorrenza solo mentre la capacità effettiva migliora senza latenza, uso di memoria, errori o limitazione inaccettabili.
- Il client nativo accetta un
concurrent.futures.Executortramite il parametro del costruttoreexecutor. Per controllare esplicitamente il pool di thread Python, passa unThreadPoolExecutor, ad esempio,DACSCacheClient(executor=ThreadPoolExecutor(max_workers=8)). Conservare un riferimento all'executor, lasciarlo attivo fino a quando tutte le letture non terminano, e arrestarlo dopo aver chiamatoawait client.shutdown(). - Un pool di thread più grande non rende concorrenti le chiamate sequenziali. Assegnare le attività dell'applicazione così come i worker executor, e utilizzare un buffer separato per ogni lettura attiva.
Tieni conto della concorrenza tra tutti i processi worker e i pod. Aumentare la concorrenza di ogni pod durante una scale-out può sovraccaricare gli stessi nodi di cache o aumentare i download duplicati di Blob in caso di cache miss con cache fredda.
Configura la dimensione del chunk della cache
Imposta SI_streamingChunkSize in byte sui pod applicativi per configurare la dimensione del chunk della cache. Ad esempio, la seguente impostazione utilizza chunk da 3 MiB:
env:
- name: SI_streamingChunkSize
value: "3145728"
Imposta questa variabile prima di creare il primo client in un processo. Riavviare i pod dell'applicazione dopo averli modificati.
La dimensione predefinita dei blocchi della cache è 32 MiB. L'argomento size impostato su read_blob(path, buffer, size, offset) specifica l'intervallo di byte richiesto dall'applicazione, non la dimensione del blocco della cache.
| Modello di accesso | Linee guida per la lettura di applicazioni |
|---|---|
| Letture del modello sequenziali di grandi dimensioni | Confronta i blocchi di cache più grandi, le dimensioni degli intervalli richiesti e la concorrenza limitata. Modificare un'impostazione alla volta. |
| Letture piccole o casuali | Richiedi solo i byte di cui l'applicazione ha bisogno. Confrontare i blocchi di cache di dimensioni inferiori per ridurre i dati recuperati fuori dall'intervallo richiesto. |
| Cache a vincoli di capacità | Misura il comportamento di occupazione e di espulsione della cache piuttosto che stimare l'uso della cache solo in base alle dimensioni del buffer di lettura dell'applicazione. |
L'applicazione Budget legge i buffer separatamente dai chunk della cache. Ad esempio, otto richieste contemporanee da 4 MiB read_blob richiedono una capacità del buffer di lettura dell'applicazione di 32 MiB, indipendentemente dalla dimensione configurata del blocco della cache. Riserva memoria pod aggiuntiva per allocazioni native client, lavoro in coda, oggetti Python e elaborazione modello. Acquisire i buffer solo dopo essere entrati nel limite di concorrenza e liberare ogni buffer in un blocco finally.
Avvertimento
BoundedBufferManager(max_memory_limit=...) limita la capacità del buffer di lettura dell'applicazione, non la memoria totale del client o il buffering nativo di upload. In 0.1.0, il budget predefinito del buffer asincrono di upload del client nativo è di 400 GiB. Questo budget non è una preallocazione né un limite sicuro di memoria Pod. Grandi letture di cold cache possono esaurire un Pod più piccolo. Per carichi di lavoro con vincoli di memoria, testare il popolamento sincrono (SI_cacheEnableSyncUpload=true) o un budget di upload asincrono limitato (SI_cacheMaxUploadBufferSizePerProcessGB). Impostare questi valori prima di creare il primo client e prevedere separatamente i buffer nativi dai buffer di lettura dell'applicazione e dall'elaborazione del modello.
Misura prima di aumentare i limiti
- Definire una baseline con un dataset fisso, il conteggio dei pod e i limiti di risorse. Misura il throughput, la latenza di lettura, la CPU, la memoria e l'uso della rete.
- Esegui il benchmark delle letture cold-cache e warm-cache separatamente. Esamina
cache_server_request_countere la telemetria di Azure Blob per distinguere il traffico della cache dal fallback diretto al Blob. - Cambia un'impostazione alla volta: concorrenza, dimensione di lettura dell'applicazione o dimensione del blocco della cache. Mantieni coerenti il dataset e le altre impostazioni quando confronti i risultati.
- Smetti di aumentare un'impostazione quando il throughput si stabilizza o la latenza, la pressione delle risorse, gli errori o il Blob throttling aumentano.
Per osservazioni lato cache, vedi Monitorare l'acceleratore distribuito per lo storage cloud.
Gestire gli errori
Tutte le eccezioni DACS derivano da DACSError:
from py_dacs_client import DACSError, DACSNotFoundError
try:
load_model_data()
except DACSNotFoundError:
handle_missing_model()
except DACSError as error:
handle_cache_or_storage_error(error)
| Exception | Meaning |
|---|---|
DACSNotFoundError |
Il percorso o la directory del Blob non esistono. |
DACSExistsError |
Un'applicazione cerca di scrivere su un blob esistente senza la sovrascrittura abilitata. |
DACSAuthenticationError |
Le credenziali sono mancanti o non valide. |
DACSPermissionError |
L'identità manca del ruolo richiesto di Blob. |
DACSTimeoutError |
Una cache o un'operazione BLOB è scaduta per timeout. |
DACSNetworkError |
Il server cache o l'endpoint Blob sono irraggiungibili. |
DACSInvalidInputError |
Un percorso o un argomento è malformato. |
OperationNotSupportedError |
L'API richiesta non è ancora implementata. |
Log di controllo
Il client dispone di controlli di logging separati per i livelli Python e nativo. Imposta entrambe le variabili per sopprimere l'output verboso da entrambi i livelli:
env:
- name: DACS_DATA_LOG_LEVEL
value: WARNING
- name: STORAGE_LOG_LEVEL
value: WARNING
DACS_DATA_LOG_LEVEL controlla il logging di Python.
STORAGE_LOG_LEVEL controlla la registrazione dei log del client nativo.