Pengujian beban dan pemantauan model AI Platform

Dokumen ini menunjukkan cara menguji dan memantau performa layanan online model machine learning (ML) yang di-deploy ke AI Platform Prediction. Dokumen ini menggunakan Locust, alat open source untuk pengujian beban.

Dokumen ini ditujukan untuk data scientist dan engineer MLOps yang ingin memantau beban kerja layanan, latensi, dan penggunaan resource model ML mereka dalam produksi.

Dokumen ini mengasumsikan bahwa Anda memiliki pengalaman dengan Google Cloud, TensorFlow, AI Platform Prediction, Cloud Monitoring, dan Jupyter Notebook.

Dokumen ini disertai dengan repositori GitHub yang menyertakan kode dan panduan deployment untuk menerapkan sistem yang dijelaskan dalam dokumen ini. Tugas-tugas tersebut dimasukkan ke dalam notebook Jupyter.

Biaya

Notebook yang Anda gunakan dalam dokumen ini menggunakan komponen Google Cloud yang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga.

Sebelum memulai

  1. 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.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

Ringkasan arsitektur

Diagram berikut menunjukkan arsitektur sistem untuk men-deploy model ML untuk prediksi online, menjalankan pengujian beban, serta mengumpulkan dan menganalisis metrik untuk performa penayangan model ML.

Arsitektur untuk men-deploy model serta mengumpulkan dan menganalisis performa model.

Diagram menunjukkan alur berikut:

  1. Model terlatih Anda mungkin berada di Cloud Storage—misalnya, SavedModel TensorFlow atau joblib scikit-learn. Atau, model dapat digabungkan ke dalam penampung penayangan kustom di Container Registry—misalnya, TorchServe untuk menayangkan model PyTorch.
  2. Model di-deploy ke AI Platform Prediction sebagai REST API. AI Platform Prediction adalah layanan terkelola sepenuhnya untuk penayangan model yang mendukung berbagai jenis mesin, mendukung penskalaan otomatis berdasarkan penggunaan resource, dan mendukung berbagai akselerator GPU.
  3. Locust digunakan untuk menerapkan tugas pengujian (yaitu, perilaku pengguna). Hal ini dilakukan dengan memanggil model ML yang di-deploy ke AI Platform Prediction dan menjalankannya dalam skala besar di Google Kubernetes Engine (GKE). Hal ini menyimulasikan banyak panggilan pengguna secara bersamaan untuk menguji beban layanan prediksi model. Anda dapat memantau progres pengujian menggunakan antarmuka web Locust.
  4. Locust mencatat statistik pengujian ke Cloud Logging. Entri log yang dibuat oleh pengujian Locust digunakan untuk menentukan kumpulan metrik berbasis log di Cloud Monitoring. Metrik ini melengkapi metrik AI Platform Prediction standar.
  5. Metrik AI Platform dan metrik Locust kustom tersedia untuk visualisasi di dasbor Cloud Monitoring secara real time. Setelah pengujian selesai, metrik juga dikumpulkan secara terprogram sehingga Anda dapat menganalisis dan memvisualisasikan metrik di notebook Vertex AI Workbench yang dikelola pengguna.

Notebook Jupyter untuk skenario ini

Semua tugas untuk menyiapkan dan men-deploy model, menjalankan pengujian Locust, serta mengumpulkan dan menganalisis hasil pengujian dikoding dalam notebook Jupyter berikut. Untuk melakukan tugas, jalankan urutan sel di setiap notebook.

  1. 01-prepare-and-deploy.ipynb. Anda menjalankan notebook ini untuk menyiapkan SavedModel TensorFlow untuk inferensi dan men-deploy model ke AI Platform Prediction.
  2. 02-perf-testing.ipynb. Anda menjalankan notebook ini untuk membuat metrik berbasis log di Cloud Monitoring untuk pengujian Locust, serta men-deploy pengujian Locust ke GKE dan menjalankannya.
  3. 03-analyze-results.ipynb. Anda menjalankan notebook ini untuk mengumpulkan dan menganalisis hasil pengujian beban Locust dari metrik AI Platform standar yang dibuat oleh Cloud Monitoring, dan dari metrik Locust kustom.

Melakukan inisialisasi lingkungan Anda

Seperti yang dijelaskan dalam file README.md dari repositori GitHub terkait, Anda perlu melakukan langkah-langkah berikut untuk menyiapkan lingkungan guna menjalankan notebook:

  1. Di project Google Cloud Anda, buat bucket Cloud Storage, yang diperlukan untuk menyimpan model terlatih dan konfigurasi pengujian Locust. Catat nama yang Anda gunakan untuk bucket karena Anda akan memerlukannya nanti.
  2. Buat ruang kerja Cloud Monitoring dalam project Anda.
  3. Buat cluster Google Kubernetes Engine yang memiliki CPU yang diperlukan. Node pool harus memiliki akses ke Cloud API.
  4. Buat instance notebook yang dikelola pengguna Vertex AI Workbench yang menggunakan TensorFlow 2. Untuk tutorial ini, Anda tidak memerlukan GPU karena Anda tidak melatih model. (GPU dapat berguna dalam skenario lain, terutama untuk mempercepat pelatihan model Anda.)

Membuka JupyterLab

Untuk mengerjakan tugas pada skenario ini, Anda perlu membuka lingkungan JupyterLab dan mendapatkan notebook.

  1. Di konsol Google Cloud, buka halaman Notebooks.

    Buka Notebooks

  2. Di tab User-managed notebooks, klik Open Jupyterlab di samping lingkungan notebook yang Anda buat.

    Tindakan ini akan membuka lingkungan JupyterLab di browser Anda.

  3. Untuk meluncurkan tab terminal, klik ikon Terminal di tab Peluncur.

  4. Di terminal, clone repositori GitHub mlops-on-gcp:

    git clone https://github.com/GoogleCloudPlatform/mlops-on-gcp.git
    

    Setelah perintah selesai, Anda akan melihat folder mlops-on-gcp di file browser. Di folder tersebut, Anda akan melihat notebook yang Anda gunakan dalam dokumen ini.

Mengonfigurasi setelan notebook

Di bagian ini, Anda akan menetapkan variabel di notebook dengan nilai yang spesifik untuk konteks, dan menyiapkan lingkungan untuk menjalankan kode untuk skenario tersebut.

  1. Buka direktori model_serving/caip-load-testing.
  2. Untuk setiap tiga notebook, lakukan hal berikut:
    1. Buka notebook.
    2. Jalankan sel di bagian Configure Google Cloud environment settings.

Bagian berikut menyoroti bagian-bagian penting dari proses tersebut serta menjelaskan aspek desain dan kode.

Menayangkan model untuk prediksi online

Model ML yang digunakan dalam dokumen ini menggunakan model klasifikasi gambar ResNet V2 101 yang telah dilatih sebelumnya dari TensorFlow Hub. Namun, Anda dapat menyesuaikan pola dan teknik desain sistem dari dokumen ini ke domain lain dan ke jenis model lainnya.

Kode untuk menyiapkan dan menayangkan model ResNet 101 ada di notebook 01-prepare-and-deploy.ipynb. Anda menjalankan sel di notebook untuk melakukan tugas berikut:

  1. Download dan jalankan model ResNet dari TensorFlow Hub.
  2. Buat tanda tangan penayangan untuk model.
  3. Mengekspor model sebagai SavedModel.
  4. Men-deploy SavedModel ke AI Platform Prediction.
  5. Validasi model yang di-deploy.

Bagian berikutnya dalam dokumen ini memberikan detail tentang cara menyiapkan model ResNet dan cara men-deploy-nya.

Menyiapkan model ResNet untuk deployment

Model ResNet dari TensorFlow Hub tidak memiliki tanda tangan penayangan karena dioptimalkan untuk rekomposisi dan penyesuaian. Oleh karena itu, Anda perlu membuat tanda tangan penayangan untuk model agar dapat menayangkan model untuk prediksi online.

Selain itu, untuk menayangkan model, sebaiknya sematkan logika rekayasa fitur ke dalam antarmuka penayangan. Dengan melakukan hal ini, Anda akan menjamin kesesuaian antara prapemrosesan dan penayangan model, bukan bergantung pada aplikasi klien untuk memproses data dalam format yang diperlukan. Anda juga harus menyertakan pascapemrosesan di antarmuka penayangan, seperti mengonversi ID class menjadi label class.

Agar model ResNet dapat ditayangkan, Anda perlu menerapkan tanda tangan penayangan yang menjelaskan metode inferensi model. Oleh karena itu, kode notebook menambahkan dua tanda tangan:

  • Tanda tangan default. Tanda tangan ini mengekspos metode predict default dari model ResNet V2 101; metode default tidak memiliki logika pra-pemrosesan atau pascapemrosesan.
  • Prapemrosesan dan pascapemrosesan tanda tangan. Input yang diharapkan untuk antarmuka ini memerlukan prapemrosesan yang relatif kompleks, termasuk encoding, penskalaan, dan normalisasi gambar. Oleh karena itu, model ini juga mengekspos tanda tangan alternatif yang menyematkan logika pra-pemrosesan dan pascapemrosesan. Tanda tangan ini menerima gambar mentah yang belum diproses dan menampilkan daftar label class yang diberi peringkat dan probabilitas label terkait.

Tanda tangan dibuat di class modul kustom. Class ini berasal dari class dasar tf.Module yang mengenkapsulasi model ResNet. Class kustom memperluas class dasar dengan metode yang menerapkan logika prapemrosesan gambar dan pascapemrosesan output. Metode default modul kustom dipetakan ke metode default model ResNet dasar untuk mempertahankan antarmuka analog. Modul kustom diekspor sebagai SavedModel yang menyertakan model asli, logika prapemrosesan, dan dua tanda tangan penayangan.

Implementasi class modul kustom ditampilkan dalam cuplikan kode berikut:

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)

Cuplikan kode berikut menunjukkan cara model diekspor sebagai SavedModel dengan tanda tangan penayangan yang ditentukan sebelumnya:

...

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)

Men-deploy model ke AI Platform Prediction

Saat model diekspor sebagai SavedModel, tugas berikut akan dilakukan:

  • Model diupload ke Cloud Storage.
  • Objek model dibuat di AI Platform Prediction.
  • Versi model dibuat untuk SavedModel.

Cuplikan kode berikut dari notebook menunjukkan perintah yang melakukan tugas ini.

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}

Perintah ini membuat jenis mesin n1-standard-8 untuk layanan prediksi model beserta akselerator GPU nvidia-tesla-p4.

Setelah menjalankan sel notebook yang memiliki perintah ini, Anda dapat memverifikasi bahwa versi model di-deploy dengan melihatnya di halaman AI Platform Models di konsol Google Cloud. Outputnya mirip dengan hal berikut ini:

Memverifikasi bahwa model di-deploy melalui konsol Google Cloud.

Membuat metrik Cloud Monitoring

Setelah model disiapkan untuk ditayangkan, Anda dapat mengonfigurasi metrik yang memungkinkan Anda memantau performa penayangan. Kode untuk mengonfigurasi metrik ada di notebook 02-perf-testing.ipynb.

Bagian pertama notebook 02-perf-testing.ipynb membuat metrik berbasis log kustom di Cloud Monitoring menggunakan Python Cloud Logging SDK. Metrik ini didasarkan pada entri log yang dihasilkan oleh tugas Locust. Metode log_stats menulis entri log ke log Cloud Logging bernama locust.

Setiap entri log menyertakan kumpulan key-value pair dalam format JSON, seperti yang tercantum dalam tabel berikut. Metrik didasarkan pada subset kunci dari entri log.

Kunci Deskripsi nilai Penggunaan
test_id ID pengujian Memfilter
atribut
model Nama model AI Platform Prediction
model_version Versi model AI Platform Prediction
latency Waktu respons persentil ke-95, yang dihitung selama periode geser 10 detik Nilai
metrik
num_requests Jumlah total permintaan sejak pengujian dimulai
num_failures Jumlah total kegagalan sejak pengujian dimulai
user_count Jumlah pengguna simulasi
rps Permintaan per detik

Cuplikan kode berikut menunjukkan fungsi create_locust_metric di notebook yang membuat metrik berbasis log kustom.

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

Cuplikan kode berikut menunjukkan cara metode create_locust_metric dipanggil di notebook untuk membuat empat metrik Locust kustom yang ditampilkan dalam tabel sebelumnya.

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

Notebook membuat dasbor Cloud Monitoring kustom yang disebut AI Platform Prediction and Locust. Dasbor menggabungkan metrik Prediksi AI Platform standar dan metrik kustom yang dibuat berdasarkan log Locust.

Untuk informasi selengkapnya, lihat dokumentasi Cloud Logging API.

Dasbor ini dan diagramnya dapat dibuat secara manual. Namun, notebook menyediakan cara terprogram untuk membuatnya menggunakan template JSON monitoring-template.json. Kode tersebut menggunakan class DashboardsServiceClient untuk memuat template JSON dan membuat dasbor di Cloud Monitoring, seperti yang ditunjukkan dalam cuplikan kode berikut:

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)

Setelah dasbor dibuat, Anda dapat melihatnya dalam daftar dasbor Cloud Monitoring di Konsol Google Cloud:

Halaman konsol Google Cloud yang menampilkan daftar dasbor Monitoring.

Anda dapat mengklik dasbor untuk membukanya dan melihat diagram. Setiap diagram menampilkan metrik dari AI Platform Prediction atau dari log Locust, seperti yang ditunjukkan dalam screenshot berikut.

Berbagai diagram yang menampilkan metrik berdasarkan data log.

Men-deploy pengujian Locust ke cluster GKE

Sebelum men-deploy sistem Locust ke GKE, Anda harus membangun image container Docker yang berisi logika pengujian yang di-build ke dalam file task.py. Image ini berasal dari image baseline locust.io dan digunakan untuk Pod master dan pekerja Locust.

Logika untuk mem-build dan men-deploy ada di notebook pada bagian 3. Men-deploy Locust ke cluster GKE. Image dibuat menggunakan kode berikut:

image_uri = 'gcr.io/{}/locust'.format(PROJECT_ID)

!gcloud builds submit --tag {image_uri} locust/locust-image

Proses deployment yang dijelaskan dalam notebook telah ditentukan menggunakan Kustomize. Manifes deployment Kustomize Locust menentukan file berikut yang menentukan komponen:

  • locust-master. File ini menentukan deployment yang menghosting antarmuka web tempat Anda memulai pengujian dan melihat statistik langsung.
  • locust-worker. File ini menentukan deployment yang menjalankan tugas untuk menguji beban layanan prediksi model ML Anda. Biasanya, beberapa pekerja dibuat untuk menyimulasikan efek beberapa pengguna serentak yang melakukan panggilan ke API layanan prediksi Anda.
  • locust-worker-service. File ini menentukan layanan yang mengakses antarmuka web di locust-master melalui load balancer HTTP.

Anda perlu mengupdate manifes default sebelum cluster di-deploy. Manifes default terdiri dari file kustomization.yaml dan patch.yaml; Anda harus melakukan perubahan pada kedua file tersebut.

Dalam file kustomization.yaml, lakukan hal berikut:

  • Tetapkan nama image Locust kustom. Tetapkan kolom newName di bagian images ke nama image kustom yang Anda build sebelumnya.
  • Secara opsional, tetapkan jumlah Pod pekerja. Konfigurasi default men-deploy 32 Pod pekerja. Untuk mengubah angka, ubah kolom count di bagian replicas. Pastikan cluster GKE Anda memiliki CPU dalam jumlah yang memadai untuk pekerja Locust.
  • Tetapkan bucket Cloud Storage untuk konfigurasi pengujian dan file payload. Di bagian configMapGenerator, pastikan bahwa hal berikut telah ditetapkan:
    • LOCUST_TEST_BUCKET. Tetapkan ini ke nama bucket Cloud Storage yang Anda buat sebelumnya.
    • LOCUST_TEST_CONFIG. Tetapkan ini ke nama file konfigurasi pengujian. Dalam file YAML, nilai ini ditetapkan ke test-config.json, tetapi Anda dapat mengubahnya jika ingin menggunakan nama yang berbeda.
    • LOCUST_TEST_PAYLOAD. Tetapkan ke nama file payload pengujian. Dalam file YAML, nilai ini ditetapkan ke test-payload.json, tetapi Anda dapat mengubahnya jika ingin menggunakan nama yang berbeda.

Dalam file patch.yaml, lakukan hal berikut:

  • Secara opsional, ubah node pool yang menghosting master dan pekerja Locust. Jika Anda men-deploy workload Locust ke node pool selain default-pool, temukan bagian matchExpressions, lalu di bagian values, perbarui nama node pool tempat workload Locust akan di-deploy.

Setelah melakukan perubahan ini, Anda dapat mem-build penyesuaian ke dalam manifes Kustomize dan menerapkan deployment Locust (locust-master, locust-worker, dan locust-master-service) ke cluster GKE. Perintah berikut di notebook akan melakukan tugas-tugas ini:

!kustomize build locust/manifests | kubectl apply -f -

Anda dapat memeriksa beban kerja yang di-deploy di konsol Google Cloud. Outputnya mirip dengan hal berikut ini:

Konsol GKE yang menampilkan workload.

Menerapkan pengujian beban Locust

Tugas pengujian untuk Locust adalah memanggil model yang di-deploy ke AI Platform Prediction.

Tugas ini diterapkan di class AIPPClient dalam modul task.py yang ada di folder /locust/locust-image/. Cuplikan kode berikut menunjukkan implementasi class.

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

Class AIPPUser dalam file task.py mewarisi dari class locust.User untuk menyimulasikan perilaku pengguna dalam memanggil model AI Platform Prediction. Perilaku ini diterapkan dalam metode predict_task. Metode on_start dari class AIPPUser mendownload file berikut dari bucket Cloud Storage yang ditentukan dalam variabel LOCUST_TEST_BUCKET dalam file task.py:

  • test-config.json. File JSON ini menyertakan konfigurasi berikut untuk pengujian: test_id, project_id, model, dan version.
  • test-payload.json. File JSON ini menyertakan instance data dalam format yang diharapkan oleh AI Platform Prediction, beserta tanda tangan target.

Kode untuk menyiapkan data pengujian dan konfigurasi pengujian disertakan dalam notebook 02-perf-testing.ipynb di bagian 4. Konfigurasi pengujian Locust.

Konfigurasi pengujian dan instance data digunakan sebagai parameter untuk metode predict di class AIPPClient untuk menguji model target menggunakan data pengujian yang diperlukan. AIPPUser Mensimulasikan waktu tunggu 1 hingga 2 detik di antara panggilan dari satu pengguna.

Menjalankan pengujian Locust

Setelah menjalankan sel notebook untuk men-deploy beban kerja Locust ke cluster GKE, dan setelah membuat, lalu mengupload file test-config.json dan test-payload.json ke Cloud Storage, Anda dapat memulai, menghentikan, dan mengonfigurasi pengujian beban Locust baru menggunakan antarmuka web-nya. Kode di notebook mengambil URL load balancer eksternal yang mengekspos antarmuka web menggunakan perintah berikut:

%%bash
IP_ADDRESS=$(kubectl get service locust-master | awk -v  col=4 'FNR==2{print $col}')
echo http://$IP_ADDRESS:8089

Untuk melakukan pengujian, lakukan hal berikut:

  1. Di browser, masukkan URL yang Anda ambil.
  2. Untuk menyimulasikan beban kerja pengujian menggunakan konfigurasi yang berbeda, masukkan nilai ke antarmuka Locust, yang mirip dengan berikut:

    Antarmuka Locust untuk memulai pengujian Locust.

    Screenshot sebelumnya menunjukkan nilai konfigurasi berikut:

    • Jumlah total pengguna yang akan disimulasikan: 150
    • Rasio menetas: 1
    • Host: http://ml.googleapis.com
    • Jumlah pengguna yang akan ditingkatkan per langkah: 10
    • Durasi langkah: 2m

Saat pengujian berjalan, Anda dapat memantau pengujian dengan memeriksa diagram Locust. Screenshot berikut menunjukkan cara nilai ditampilkan.

Satu diagram menunjukkan jumlah total permintaan per detik:

Diagram Locust yang menampilkan permintaan per detik.

Diagram lain menunjukkan waktu respons dalam milidetik:

Diagram Locust yang menunjukkan waktu respons dalam milidetik.

Seperti yang disebutkan sebelumnya, statistik ini juga dicatat ke Cloud Logging sehingga Anda dapat membuat metrik berbasis log Cloud Monitoring kustom.

Mengumpulkan dan menganalisis hasil pengujian

Tugas berikutnya adalah mengumpulkan dan menganalisis metrik Cloud Monitoring yang dihitung dari log hasil sebagai objek DataFrame pandas sehingga Anda dapat memvisualisasikan dan menganalisis hasilnya di notebook. Kode untuk melakukan tugas ini ada di notebook 03-analyze-results.ipynb.

Kode ini menggunakan Cloud Monitoring Query Python SDK untuk memfilter dan mengambil nilai metrik, dengan nilai yang diteruskan dalam parameter project_id, test_id, start_time, end_time, model, model_version, dan log_name.

Cuplikan kode berikut menunjukkan metode yang mengambil metrik Prediksi AI Platform dan metrik berbasis log Locust kustom.

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

Data metrik diambil sebagai objek DataFrame pandas untuk setiap metrik; setiap frame data kemudian digabungkan menjadi satu objek DataFrame. Objek DataFrame akhir dengan hasil gabungan akan terlihat seperti berikut di notebook Anda:

Menampilkan frame pandas di notebook dengan objek DataFrame yang digabungkan.

Objek DataFrame yang diambil menggunakan pengindeksan hierarkis untuk nama kolom. Alasannya adalah karena beberapa metrik berisi beberapa deret waktu. Misalnya, metrik duty_cycle GPU menyertakan deret waktu pengukuran untuk setiap GPU yang digunakan dalam deployment, yang ditunjukkan sebagai replica_id. Tingkat teratas indeks kolom menampilkan nama untuk setiap metrik. Tingkat kedua adalah replika ID. Tingkat ketiga menampilkan tanda tangan model. Semua metrik disejajarkan pada linimasa yang sama.

Diagram berikut menunjukkan penggunaan GPU, penggunaan CPU, dan latensi seperti yang Anda lihat di notebook.

Pemakaian GPU:

Diagram garis yang menunjukkan penggunaan GPU dari waktu ke waktu.

Pemakaian CPU:

Diagram garis yang menunjukkan penggunaan CGPU dari waktu ke waktu.

Latensi:

Diagram garis yang menunjukkan latensi dari waktu ke waktu.

Diagram menunjukkan perilaku dan urutan berikut:

  1. Seiring meningkatnya beban kerja (jumlah pengguna), penggunaan CPU dan GPU akan meningkat. Akibatnya, latensi meningkat, dan perbedaan antara latensi model dan latensi total meningkat hingga mencapai puncaknya sekitar pukul 20.40.
  2. Pada pukul 20.40, penggunaan GPU mencapai 100%, sedangkan diagram CPU menunjukkan bahwa penggunaan mencapai 4 CPU. Contoh ini menggunakan mesin n1-standard-8 dalam pengujian ini, yang memiliki 8 CPU. Dengan demikian, penggunaan CPU mencapai 50%.
  3. Pada tahap ini, penskalaan otomatis akan menambahkan kapasitas: node penayangan baru ditambahkan dengan replika GPU tambahan. Penggunaan replika GPU pertama menurun, dan penggunaan replika GPU kedua meningkat.
  4. Latensi menurun saat replika baru mulai menayangkan prediksi, yang berkonvergensi sekitar 200 milidetik.
  5. Penggunaan CPU berkonvergensi pada sekitar 250% untuk setiap replika—yaitu, menggunakan 2,5 CPU dari 8 CPU. Nilai ini menunjukkan bahwa Anda dapat menggunakan mesin n1-standard-4, bukan mesin n1-standard-8.

Pembersihan

Agar tidak dikenai biaya pada Google Cloud Anda untuk resource yang digunakan dalam dokumen ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Jika Anda ingin mempertahankan project Google Cloud, tetapi menghapus resource yang Anda buat, hapus cluster Google Kubernetes Engine dan model AI Platform yang di-deploy.

Langkah selanjutnya