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 AI Generatif, pengguna GKE baru atau lama, Engineer ML, dan engineer LLMOps (DevOps) yang tertarik untuk mengoptimalkan beban kerja LLM mereka menggunakan GPU dengan Kubernetes.

Setelah mempelajari panduan ini, Anda akan dapat:

  • Pilih teknik pengoptimalan LLM pasca-pelatihan, termasuk kuantisasi, paralelisme tensor, dan pengoptimalan memori.
  • Pertimbangkan pertimbangan 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 inferensi LLM

Tidak seperti workload non-AI, workload LLM biasanya menunjukkan latensi yang lebih tinggi dan throughput yang lebih rendah karena bergantung pada operasi perkalian matriks. Untuk meningkatkan performa inferensi LLM, Anda dapat menggunakan akselerator hardware khusus (misalnya, GPU dan TPU) dan 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 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, 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 ke /kubernetes-engine-samples/ai-ml/llm-serving-gemma/.

Praktik terbaik: Kuantisasi

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 melibatkan pertukaran: ukuran model yang lebih kecil dapat menyebabkan penurunan akurasi.

Ada berbagai metode kuantisasi, masing-masing dengan kelebihan dan kekurangan yang unik. Beberapa di antaranya, 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 menyajikan model di 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 dikuantisasi sebelumnya, sehingga dapat menjadi pilihan yang sesuai jika versi yang telah dikuantisasi sebelumnya tidak tersedia.

Teknik kuantisasi terbaik yang 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 dikuantisasi terlebih dahulu. 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 FP8 E5M2, 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 penting saat Anda menjalankan model besar yang melebihi kapasitas memori GPU tunggal. Pendekatan ini bisa 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 nilainya.

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

Cuplikan berikut menunjukkan cara mengoptimalkan model yang di-tune untuk mengikuti perintah Gemma 7B 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 yang disesuaikan untuk mengikuti perintah Gemma 7B 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 kilat. Strategi ini meningkatkan efisiensi memori, sehingga memungkinkan urutan input yang lebih panjang dan mengurangi waktu tunggu 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 konteksnya. Namun, lapisan ini menyimpan bobot token input, kunci (K), dan nilai (V) dalam vRAM GPU. Jadi, saat urutan input bertambah panjang, hal ini menyebabkan pertumbuhan kuadratik dalam ukuran dan waktu komputasi.

Penggunaan KV caching sangat berguna saat Anda berurusan dengan urutan input yang panjang, yang dapat menyebabkan overhead self-attention menjadi signifikan. Pendekatan pengoptimalan ini mengurangi pemrosesan komputasi menjadi kompleksitas linear.

Teknik khusus untuk mengoptimalkan mekanisme atensi di LLM meliputi:

  • Atensi ber-paging: Atensi ber-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 panjang tanpa kehabisan memori GPU.
  • Flash attention: Flash attention mengurangi hambatan memori GPU dengan meminimalkan transfer data antara RAM GPU dan cache L1 selama pembuatan token. Hal ini menghilangkan waktu tunggu untuk core komputasi, sehingga meningkatkan performa inferensi dan pelatihan GPU secara signifikan.

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 inferensi TGI memeriksa persyaratan memori selama startup dan tidak dimulai jika footprint 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 menyajikan model yang telah disesuaikan untuk mengikuti perintah Gemma 7B 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 untuk perintah Gemma 7B, dengan panjang konteks default 8192, melampaui kapasitas memori GPU NVIDIA L4 tunggal. Untuk men-deploy di L4, batasi panjang gabungan perintah dan output dengan menyetel --max-model-len ke nilai di bawah 640. Penyesuaian ini memungkinkan model dijalankan di satu GPU L4 meskipun panjang konteks defaultnya 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 trade-off akurasi.
Throughput
  • Menskalakan secara horizontal: Tingkatkan jumlah replika penayangan (Pod) untuk mendistribusikan beban kerja.
  • Gunakan paralelisme tensor: Untuk model besar yang melebihi kapasitas GPU tunggal, gunakan paralelisme tensor untuk menyebarkan komputasi di beberapa GPU. Untuk model yang lebih kecil, pertimbangkan beberapa replika dengan paralelisme tensor `1` untuk menghindari overhead.
  • Permintaan batch dan kuantisasi: Gabungkan permintaan dan pelajari teknik kuantisasi yang mempertahankan akurasi yang dapat diterima.
Efisiensi biaya
  • Pilih 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.
  • Batasi panjang konteks: Batasi panjang konteks untuk lebih mengurangi penggunaan memori dan memungkinkan eksekusi di GPU yang lebih kecil dan hemat biaya.

Langkah berikutnya