Praktik terbaik untuk mengoptimalkan inferensi model bahasa besar dengan GPU di Google Kubernetes Engine (GKE)


Google Kubernetes Engine (GKE) memberikan kontrol terperinci untuk inferensi model bahasa besar (LLM) dengan performa dan biaya yang optimal. Panduan ini menjelaskan praktik terbaik untuk mengoptimalkan inferensi dan penayangan LLM terbuka dengan GPU di GKE menggunakan framework penayangan vLLM dan Text Generation Inference (TGI).

Untuk mengetahui checklist ringkasan semua praktik terbaik, lihat Ringkasan checklist.

Tujuan

Panduan ini ditujukan untuk pelanggan Generative AI, pengguna GKE baru atau lama, Engineer ML, dan engineer LLMOps (DevOps) yang tertarik untuk mengoptimalkan beban kerja LLM mereka menggunakan GPU dengan Kubernetes.

Di akhir panduan ini, Anda akan dapat:

  • Pilih teknik pengoptimalan LLM pasca-pelatihan, termasuk kuantisasi, paralelisme tensor, dan pengoptimalan memori.
  • Pertimbangkan kompromi tingkat tinggi saat mempertimbangkan teknik pengoptimalan ini.
  • Deploy model LLM terbuka ke GKE menggunakan framework penayangan seperti vLLM atau TGI dengan setelan pengoptimalan diaktifkan.

Ringkasan teknik pengoptimalan penayangan LLM

Tidak seperti workload non-AI, workload LLM biasanya menunjukkan latensi yang lebih tinggi dan throughput yang lebih rendah karena mengandalkan operasi perkalian matriks. Untuk meningkatkan performa inferensi LLM, Anda dapat menggunakan akselerator hardware khusus (misalnya, GPU dan TPU) serta framework penayangan yang dioptimalkan.

Anda dapat menerapkan satu atau beberapa praktik terbaik berikut untuk mengurangi latensi beban kerja LLM sekaligus meningkatkan throughput dan efisiensi biaya:

Contoh dalam panduan ini menggunakan LLM Gemma 7B bersama dengan framework penayangan vLLM atau TGI untuk menerapkan praktik terbaik ini; namun, konsep dan fitur yang dijelaskan berlaku untuk sebagian besar LLM terbuka yang populer.

Sebelum memulai

Sebelum Anda mencoba contoh dalam panduan ini, selesaikan tugas prasyarat berikut:

  1. Ikuti petunjuk dalam panduan ini untuk mendapatkan akses ke model Gemma, menyiapkan lingkungan Anda, serta membuat dan mengonfigurasi resource Google Cloud:

    Pastikan untuk menyimpan token akses Hugging Face ke secret Kubernetes Anda.

  2. Clone repositori contoh https://github.com/GoogleCloudPlatform/kubernetes-engine-samples/ ke lingkungan pengembangan lokal Anda.

  3. Ubah direktori kerja Anda menjadi /kubernetes-engine-samples/ai-ml/llm-serving-gemma/.

Praktik terbaik: Kuantifikasi

Kuantisasi adalah teknik yang analog dengan kompresi gambar lossy yang mengurangi ukuran model dengan merepresentasikan bobot dalam format presisi yang lebih rendah (8-bit atau 4-bit), sehingga menurunkan persyaratan memori. Namun, seperti kompresi gambar, kuantisasi memerlukan kompromi: penurunan ukuran model dapat menyebabkan penurunan akurasi.

Ada berbagai metode kuantisasi, masing-masing dengan kelebihan dan kekurangannya yang unik. Beberapa, seperti AWQ dan GPTQ, memerlukan pra-kuantisasi dan tersedia di platform seperti Hugging Face atau Kaggle. Misalnya, jika Anda menerapkan GPTQ pada model Llama-2 13B dan AWQ pada model Gemma 7B, Anda dapat menayangkan model pada satu GPU L4, bukan dua GPU L4 tanpa kuantisasi.

Anda juga dapat melakukan kuantisasi menggunakan alat seperti AutoAWQ dan AutoGPTQ. Metode ini dapat meningkatkan latensi dan throughput. Sebaliknya, teknik yang menggunakan EETQ dan library bitsandbytes untuk kuantisasi tidak memerlukan model yang telah dikuantifikasi sebelumnya sehingga dapat menjadi pilihan yang sesuai jika versi yang telah dikuantifikasi sebelumnya tidak tersedia.

Teknik kuantisasi terbaik yang akan digunakan bergantung pada sasaran spesifik Anda, dan kompatibilitas teknik dengan framework penayangan yang ingin Anda gunakan. Untuk mempelajari lebih lanjut, lihat Panduan kuantisasi dari Hugging Face.

Pilih salah satu tab ini untuk melihat contoh penerapan kuantisasi menggunakan framework TGI atau vLLM:

TGI

GKE mendukung opsi kuantisasi ini dengan TGI:

  • awq
  • gptq
  • eetq
  • bitsandbytes
  • bitsandbytes-nf4
  • bitsandbytes-fp4

Metode kuantisasi AWQ dan GPTQ memerlukan model yang telah dikuantisasi sebelumnya, sedangkan kuantisasi EETQ dan bitsandbytes dapat diterapkan ke model apa pun. Untuk mempelajari opsi ini lebih lanjut, lihat artikel Hugging Face ini.

Untuk menggunakan kuantisasi, tetapkan parameter -–quantize saat memulai server model.

Cuplikan berikut menunjukkan cara mengoptimalkan Gemma 7B dengan kuantisasi bitsandbytes menggunakan TGI di GKE.

args:
- --model-id=$(MODEL_ID)
- --num-shard=2
- --quantize=bitsandbytes

Untuk menerapkan konfigurasi ini, gunakan perintah berikut:

kubectl apply -f tgi/tgi-7b-bitsandbytes.yaml

vLLM

GKE mendukung opsi kuantisasi ini dengan vLLM:

Untuk menggunakan kuantisasi model dengan vLLM, model harus dikuantifikasi sebelumnya. Saat Anda memulai runtime, tetapkan parameter –quantization.

Cuplikan berikut menunjukkan cara mengoptimalkan model Gemma 7B dengan kuantisasi awq menggunakan vLLM di GKE:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --quantization=awq
env:
- name: MODEL_ID
  value: google/gemma-7b-AWQ
resources:
  requests:
    nvidia.com/gpu: 1
  limits:
    nvidia.com/gpu: 1

Untuk menerapkan konfigurasi ini, gunakan perintah berikut:

kubectl apply -f vllm/vllm-7b-awq.yaml

Meningkatkan latensi dengan menggunakan kuantisasi cache KV

Anda dapat menggunakan kuantisasi Cache KV FP8 E5M2 untuk mengurangi footprint memori cache KV secara signifikan dan meningkatkan latensi, terutama untuk ukuran batch besar. Namun, hal ini mengurangi akurasi inferensi.

Untuk mengaktifkan kuantisasi Cache KV E5M2 FP8, tetapkan parameter --kv-cache-dtype fp8_e5m2:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --kv-cache-dtype=fp8_e5m2
- --max-model-len=1200
resources:
  requests:
    cpu: "2"
    memory: "25Gi"
    ephemeral-storage: "25Gi"
    nvidia.com/gpu: 1
  limits:
    cpu: "2"
    memory: "25Gi"
    ephemeral-storage: "25Gi"
    nvidia.com/gpu: 1

Untuk menerapkan konfigurasi ini, gunakan perintah berikut:

kubectl apply -f vllm/vllm-7b-kvcache.yaml

Praktik terbaik: Paralelisme tensor

Paralelisme tensor adalah teknik yang mendistribusikan beban komputasi di beberapa GPU, yang sangat penting saat Anda menjalankan model besar yang melebihi kapasitas memori satu GPU. Pendekatan ini dapat lebih hemat biaya karena memungkinkan Anda menggunakan beberapa GPU yang terjangkau, bukan satu GPU yang mahal. Hal ini juga dapat meningkatkan throughput inferensi model. Paralelisme tensor memanfaatkan fakta bahwa operasi tensor dapat dilakukan secara independen pada potongan data yang lebih kecil.

Untuk mempelajari teknik ini lebih lanjut, lihat panduan Tensor Parallelism dari Hugging Face.

Pilih salah satu tab ini untuk melihat contoh penerapan paralelisme tensor menggunakan framework TGI atau vLLM:

TGI

Dengan TGI, runtime penayangan akan menggunakan semua GPU yang tersedia untuk Pod secara default. Anda dapat menetapkan jumlah GPU yang akan digunakan dengan menentukan parameter --num-shard dengan jumlah GPU sebagai nilai.

Lihat dokumentasi Hugging Face untuk mengetahui daftar model yang didukung untuk paralelisme tensor.

Cuplikan berikut menunjukkan cara mengoptimalkan model Gemma 7B yang disesuaikan dengan petunjuk menggunakan paralelisme tensor dan dua GPU L4:

args:
- --model-id=$(MODEL_ID)
- --num-shard=2

Untuk menerapkan konfigurasi ini, gunakan perintah berikut:

kubectl apply -f tgi/tgi-7b-it-tensorparallelism.yaml

Di cluster GKE Autopilot, menjalankan perintah ini akan membuat Pod dengan persyaratan resource minimum sebesar 21 vCPU dan memori 78 GiB.

vLLM

vLLM mendukung inferensi paralel tensor terdistribusi. vLLM mengaktifkan fitur secara default jika ada lebih dari satu GPU yang tersedia.

Cuplikan berikut menunjukkan cara mengoptimalkan model Gemma 7B yang disesuaikan dengan petunjuk menggunakan paralelisme tensor dan dua GPU L4:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=2

Untuk menerapkan konfigurasi ini, gunakan perintah berikut:

kubectl apply -f vllm/vllm-7b-it-tensorparallelism.yaml

Di cluster GKE Autopilot, menjalankan perintah ini akan membuat Pod dengan persyaratan resource minimum sebesar 21 vCPU dan memori 78 GiB.

Praktik terbaik: Pengoptimalan memori model

Mengoptimalkan penggunaan memori LLM sangat penting untuk inferensi yang efisien. Bagian ini memperkenalkan strategi pengoptimalan lapisan perhatian, seperti perhatian berhalaman dan perhatian flash. Strategi ini meningkatkan efisiensi memori, sehingga memungkinkan urutan input yang lebih lama dan mengurangi waktu tidak ada aktivitas GPU. Bagian ini juga menjelaskan cara menyesuaikan ukuran input dan output model agar sesuai dengan batasan memori dan mengoptimalkan framework penayangan tertentu.

Pengoptimalan lapisan perhatian

Lapisan self-attention memungkinkan model memahami konteks dalam tugas pemrosesan bahasa, karena makna kata dapat berubah bergantung pada konteks. Namun, lapisan ini menyimpan bobot token input, kunci (K), dan nilai (V) di vRAM GPU. Dengan demikian, seiring urutan input yang semakin panjang, hal ini akan menyebabkan pertumbuhan kuadrat dalam ukuran dan waktu komputasi.

Penggunaan cache KV sangat berguna saat Anda menangani urutan input yang panjang, dengan overhead perhatian mandiri yang dapat menjadi signifikan. Pendekatan pengoptimalan ini mengurangi pemrosesan komputasi menjadi kompleksitas linear.

Teknik khusus untuk mengoptimalkan mekanisme perhatian di LLM meliputi:

  • Atensi paging: Atensi paging meningkatkan pengelolaan memori untuk model besar dan urutan input yang panjang dengan menggunakan teknik paging, mirip dengan memori virtual OS. Hal ini secara efektif mengurangi fragmentasi dan duplikasi dalam cache KV, sehingga memungkinkan urutan input yang lebih lama tanpa kehabisan memori GPU.
  • Flash attention: Flash attention mengurangi bottleneck memori GPU dengan meminimalkan transfer data antara RAM GPU dan cache L1 selama pembuatan token. Hal ini menghilangkan waktu tidak ada aktivitas untuk core komputasi, sehingga secara signifikan meningkatkan performa inferensi dan pelatihan untuk GPU.

Penyesuaian ukuran input dan output model

Persyaratan memori bergantung pada ukuran input dan output. Output yang lebih panjang dan lebih banyak konteks memerlukan lebih banyak resource, sedangkan output yang lebih pendek dan lebih sedikit konteks dapat menghemat biaya dengan menggunakan GPU yang lebih kecil dan lebih murah.

Pilih salah satu tab ini untuk melihat contoh penyesuaian persyaratan memori input dan output model dalam framework TGI atau vLLM:

TGI

Runtime penayangan TGI memeriksa persyaratan memori selama startup dan tidak dimulai jika jejak memori model maksimum yang mungkin tidak sesuai dengan memori GPU yang tersedia. Pemeriksaan ini menghilangkan error kehabisan memori (OOM) pada workload yang membutuhkan banyak memori.

GKE mendukung parameter TGI berikut untuk mengoptimalkan persyaratan memori model:

Cuplikan berikut menunjukkan cara menayangkan model Gemma 7B yang disesuaikan dengan petunjuk dengan satu GPU L4, dengan setelan parameter --max-total-tokens=3072, --max-batch-prefill-tokens=512, --max-input-length=512:

args:
- --model-id=$(MODEL_ID)
- --num-shard=1
- --max-total-tokens=3072 
- --max-batch-prefill-tokens=512
- --max-input-length=512
env:
- name: MODEL_ID
  value: google/gemma-7b

Untuk menerapkan konfigurasi ini, gunakan perintah berikut:

kubectl apply -f tgi/tgi-7b-token.yaml

vLLM

Di vLLM, konfigurasikan panjang konteks model, yang secara langsung memengaruhi ukuran cache KV dan persyaratan RAM GPU. Panjang konteks yang lebih kecil memungkinkan penggunaan GPU yang lebih terjangkau. Nilai default adalah jumlah maksimum token yang diterima model. Batasi panjang konteks maksimum dengan --max-model-len MAX_MODEL_LEN jika diperlukan.

Misalnya, model yang disesuaikan dengan petunjuk Gemma 7B, dengan panjang konteks default 8192, melebihi kapasitas memori satu GPU NVIDIA L4. Untuk men-deploy di L4, batasi panjang gabungan perintah dan output dengan menetapkan --max-model-len ke nilai di bawah 640. Penyesuaian ini memungkinkan model dijalankan di satu GPU L4 meskipun panjang konteks default-nya besar.

Untuk men-deploy dengan batas token yang diubah, gunakan cuplikan berikut:

args:
- --model=$(MODEL_ID)
- --tensor-parallel-size=1
- --max-model-len=600

Untuk menerapkan konfigurasi ini, gunakan perintah berikut:

kubectl apply -f vllm/vllm-7b-token.yaml

Ringkasan checklist

Sasaran Pengoptimalan Praktik
Latensi
  • Prioritaskan GPU yang canggih: Pertimbangkan untuk mengupgrade ke GPU dengan kemampuan komputasi dan throughput I/O memori yang lebih tinggi.
  • Jelajahi kuantisasi: Teknik seperti AWQ dapat meningkatkan latensi, tetapi perhatikan potensi kompromi akurasi.
Throughput
  • Menskalakan secara horizontal: Meningkatkan jumlah replika penayangan (Pod) untuk mendistribusikan beban kerja.
  • Gunakan paralelisme tensor: Untuk model besar yang melebihi kapasitas satu GPU, gunakan paralelisme tensor untuk menyebarkan komputasi di beberapa GPU. Untuk model yang lebih kecil, pertimbangkan beberapa replika dengan paralelisme tensor `1` untuk menghindari overhead.
  • Membuat permintaan secara massal dan melakukan kuantisasi: Menggabungkan permintaan dan mempelajari teknik kuantisasi yang mempertahankan akurasi yang dapat diterima.
Efisiensi biaya
  • Memilih model yang lebih kecil: Pilih model dalam keluarga yang sesuai dengan batasan resource dan anggaran Anda.
  • Terapkan kuantisasi: Gunakan kuantisasi untuk mengurangi persyaratan memori, terutama saat menangani model yang lebih besar.
  • Batas panjang konteks: Batasi panjang konteks untuk lebih mengurangi penggunaan memori dan memungkinkan eksekusi pada GPU yang lebih kecil dan lebih hemat biaya.

Langkah selanjutnya