Bu belge, daha hızlı Web AI için WebAssembly ve WebGPU geliştirmelerinin devamıdır. Bölüm 1. Devam etmeden önce bu yayını okumanızı veya IO 24'teki konuşmayı izlemenizi öneririz.
WebGPU
WebGPU, web uygulamalarının istemcinin GPU donanımına erişmesine olanak tanıyarak verimli ve son derece paralel hesaplamalar yapar. Chrome'da WebGPU'yu kullanıma sunduğumuzdan bu yana, web'de yapay zeka (AI) ve makine öğreniminin (ML) muhteşem demolarına şahit olduk.
Örneğin Web Kararlı Dağılması, doğrudan tarayıcıda metinden resim oluşturmak için yapay zekanın kullanılabileceğini gösterdi. Bu yılın başlarında Google'ın kendi Mediapipe ekibi büyük dil modeli çıkarımı için deneysel destek yayınladı.
Aşağıdaki animasyonda, Google'ın açık kaynak büyük dil modeli (LLM) olan Gemma gerçek zamanlı olarak tamamen Chrome'da çalışıyor.
Meta'nın Her Şey Modelini Segment olarak konu alan aşağıdaki Hugging Face demosu, tamamen müşteri üzerinde yüksek kaliteli nesne maskeleri üretmektedir.
Bunlar, yapay zeka ve makine öğrenimi için WebGPU'nun gücünü gösteren muhteşem projelerden sadece birkaçı. WebGPU, bu modellerin ve diğer modellerin CPU'da olduğundan önemli ölçüde daha hızlı çalışmasına olanak tanır.
Hugging Face'in metin yerleştirme için WebGPU karşılaştırması, aynı modelin CPU uygulamasıyla karşılaştırıldığında çok büyük bir hız artışı göstermektedir. Apple M1 Max dizüstü bilgisayarda WebGPU 30 kat daha hızlıydı. Bazıları ise WebGPU'nun, karşılaştırmayı 120 kattan fazla hızlandırdığını bildirmiştir.
Yapay zeka ve makine öğrenimi için WebGPU özelliklerini iyileştirme
WebGPU, işlem gölgelendiricileri sayesinde milyarlarca parametreye sahip olabilen yapay zeka ve makine öğrenimi modelleri için idealdir. Compute gölgelendiriciler GPU üzerinde çalışır ve büyük hacimli verilerde paralel dizi işlemlerinin çalıştırılmasına yardımcı olur.
Geçtiğimiz yıl WebGPU'da yapılan çok sayıda geliştirmenin yanı sıra, web'deki makine öğrenimi ve yapay zeka performansını iyileştirmek için daha fazla özellik eklemeye devam ettik. Kısa bir süre önce iki yeni özelliği kullanıma sunduk: 16 bit kayan nokta ve paketlenmiş tam sayı nokta ürünleri.
16 bit kayan nokta
ML iş yüklerinin hassasiyet gerektirmediğini unutmayın. shader-f16
, WebGPU gölgelendirme dilinde f16 türünün kullanılmasını sağlayan bir özelliktir. Bu kayan nokta türü, normal 32 bit yerine 16 bit alır. f16 daha küçük bir aralığa sahiptir ve daha az kesindir ancak birçok makine öğrenimi modeli için bu yeterlidir.
Bu özellik, verimliliği birkaç şekilde artırır:
Azaltılmış bellek: f16 öğeli tensörler, alanın yarısını kaplayarak bellek kullanımını yarıya indirir. GPU hesaplamaları genellikle bellek bant genişliğinde performans sorununa yol açar. Bu nedenle, belleğin yarısı genellikle gölgelendiricilerin iki kat daha hızlı çalışması anlamına gelir. Teknik olarak, bellek bant genişliğinden tasarruf etmek için f16'ya ihtiyacınız yoktur. Verilerin düşük kesinlikte bir biçimde depolanması ve daha sonra hesaplama için gölgelendiricide tam f32 değerine genişletmek mümkündür. Ancak GPU, verileri paketlemek ve açmak için ekstra bilgi işlem gücü harcar.
Azaltılmış veri dönüşümü: f16, veri dönüşümünü en aza indirerek daha az işlem kullanır. Düşük hassasiyetli veriler depolanabilir ve ardından dönüştürme olmaksızın doğrudan kullanılabilir.
Daha fazla paralellik: Modern GPU'lar, GPU'nun yürütme birimlerine aynı anda daha fazla değer sığabilir ve bu sayede daha çok sayıda paralel hesaplama gerçekleştirebilir. Örneğin, saniyede 5 trilyona kadar f32 kayan nokta işlemini destekleyen bir GPU, saniyede 10 trilyon f16 kayan nokta işlemini destekleyebilir.
![Metin yerleştirme için WebGPU karşılaştırmasının ekran görüntüsü](https://developer.chrome.com/static/blog/io24-webassembly-webgpu-2/image/f16-benchmark.jpeg?authuser=19&hl=tr)
shader-f16
ile, Hugging Face'in metin yerleştirme için WebGPU karşılaştırması, Apple M1 Max dizüstü bilgisayarda yapılan karşılaştırmayı f32'den 3 kat daha hızlı çalıştırıyor.
WebLLM, birden fazla büyük dil modeli çalıştırabilen bir projedir. Açık kaynak makine öğrenimi derleyici çerçevesi olan Apache TVM'yi kullanır.
WebLLM'den Llama 3 sekiz milyar parametre modelini kullanarak Paris'e bir gezi planlaması yapmasını istedim. Sonuçlar, modelin önceden doldurma aşamasında f16'nın, f32'den 2,1 kat daha hızlı olduğunu gösteriyor. Kod çözme aşamasında, bu işlem 1,3 kattan daha hızlıdır.
Uygulamalar öncelikle GPU bağdaştırıcısının f16'yı desteklediğini onaylamalı ve kullanılabiliyorsa GPU cihazı isteğinde bulunurken bunu açıkça etkinleştirmelidir. f16 desteklenmiyorsa requiredFeatures
dizisinde istekte bulunamazsınız.
// main.js
const adapter = await navigator.gpu.requestAdapter();
const supportsF16 = adapter.features.has('shader-f16');
if (supportsF16) {
// Use f16.
const device = await adapter.requestDevice({
requiredFeatures: ['shader-f16'],
});
initApp(device);
}
Ardından, WebGPU gölgelendiricilerinizde, en üstte f16'yı açıkça etkinleştirmeniz gerekir. Bundan sonra, sütunu gölgelendirici içinde diğer kayan veri türleri gibi kullanabilirsiniz.
// my-shader.wgsl
enable f16;
struct Data {
values : array<vec4<f16>>
}
@group(0) @binding(0) var<storage, read> data : Data;
@compute @workgroup_size(64) fn main(@builtin(global_invocation_id) gid : vec3u) {
let value : vec4<f16> = data.values[gid.x];
...
}
Paketlenmiş tam sayı nokta ürünleri
Birçok model, yalnızca 8 bit hassasiyetle (f16'nın yarısı) iyi performans göstermeye devam eder. Bu, segmentasyon ve nesne tanıma için LLM'ler ve görüntü modelleri arasında popülerdir. Bununla birlikte, modellerin çıkış kalitesi daha az hassasiyetle düşer. Bu nedenle, 8 bitlik niceleme her uygulama için uygun değildir.
Nispeten az sayıda GPU, 8 bit değerlerini yerel olarak destekler. Paketlenmiş tam sayılarla dolu nokta ürünleri burada devreye girer. Chrome 123'te DP4a'yı gönderdik.
Modern GPU'larda, 32 bit'lik iki tam sayı almak, bunları art arda paketlenmiş 4 bitlik tam sayı olarak yorumlamak ve bileşenleri arasında nokta çarpımını hesaplamak için özel talimatlar vardır.
Matris çarpım çekirdekleri çok sayıda nokta ürününden oluştuğundan bu, özellikle yapay zeka ve makine öğrenimi için yararlıdır.
Örneğin, 4 x 8 boyutundaki bir matrisi 8 x 1 boyutunda bir vektörle çarpalım. Bunu hesaplamak için 4 nokta çarpımının elde edilmesiyle çıktı vektörindeki değerlerin her biri hesaplanır. A, B, C ve D.
Bu çıkışların her birini hesaplama süreci aynıdır; bunlardan birini hesaplamanın adımlarına bakacağız. Her hesaplamadan önce, 8 bitlik tam sayı verilerini aritmetik yapabileceğimiz f16 gibi bir türe dönüştürmemiz gerekir. Ardından, öğe tabanlı bir çarpma işlemi çalıştırıyoruz ve son olarak tüm çarpımları topluyoruz. Toplamda, matris vektör çarpma işleminin tamamı için verilerin paketini açmak üzere kayan noktalı dönüşüm için 40 tam sayı, 32 kayan noktalı çarpım ve 28 kayan noktalı ekleme işlemi gerçekleştiriyoruz.
Daha fazla işleme sahip daha büyük matrisler için, tam sayılı nokta ürünleri iş miktarını azaltmaya yardımcı olabilir.
Sonuç vektöründeki çıkışların her biri için yerleşik WebGPU Gölgelendirme Dili dot4U8Packed
kullanarak iki paketlenmiş nokta çarpımı işlemi gerçekleştirir ve daha sonra sonuçları birbirine ekleriz. Toplamda, matris vektör çarpma işleminin tamamı için herhangi bir veri dönüştürme işlemi gerçekleştirmeyiz. 8 adet paketlenmiş nokta ürünü ve 4 tam sayı ekleme işlemi yürütüyoruz.
Paketlenmiş tamsayı nokta ürünleri, 8 bit veri ile çeşitli tüketici GPU'larında test edildi. 16 bitlik kayan noktayla karşılaştırıldığında, 8 bitin 1,6 ila 2,8 kat daha hızlı olduğunu görebiliriz. Buna ek olarak, paketlenmiş tamsayılı nokta ürünleri kullandığımızda performans daha da artar. Bu hız 1,7 ila 2,9 kat daha hızlıdır.
![Matris vektörü çarpma hızının ekran görüntüsü: f16 ve u8 karşılaştırması](https://developer.chrome.com/static/blog/io24-webassembly-webgpu-2/image/dp4a-benchmark.jpeg?authuser=19&hl=tr)
wgslLanguageFeatures
özelliğini kullanarak tarayıcı desteğini kontrol edin. GPU, paketlenmiş nokta ürünlerini yerel olarak desteklemiyorsa tarayıcı kendi uygulamasını çoklu doldurur.
// main.js
if (navigator.gpu.wgslLanguageFeatures.has('packed_4x8_integer_dot_product')) {
// Use dot4U8Packed, dot4I8Packed builtin
// functions in the shaders.
}
Bir WebGPU gölgelendiricide, paketlenmiş tam sayı ürünleri kullanmak için gereken değişiklikleri vurgulayan aşağıdaki kod snippet'i farkı (farkı).
Önce — Kısmi nokta ürünlerini "toplam" değişkeninde toplayan bir WebGPU gölgelendiricisi. Döngünün sonunda "toplam", bir vektör ile giriş matrisinin bir satırı arasında tam nokta çarpımını tutar.
// my-dot-product.wgsl @compute @workgroup_size(64) fn main(@builtin(global_invocation_id) gid : vec3u) { var sum : f16; let start = gid.x * uniforms.dim; for (var i = 0u; i < uniforms.dim; i++) { let v1 : vec4<f16> = vector.values[i]; let v2 : vec4<f16> = matrix.values[start + i]; sum += dot(v1, v2); } }
Sonra: Paketlenmiş tam sayıdaki nokta ürünlerini kullanmak için yazılan bir WebGPU gölgelendiricisi. Temel fark, bu gölgelendiricinin vektör ve matristen 4 kayan değer yüklemek yerine tek bir 32 bitlik tam sayı yüklemesidir. Bu 32 bitlik tam sayı, dört tane 8 bitlik tam sayı değerinin verilerini barındırır. Ardından, iki değerin nokta çarpımını hesaplamak için dot4U8Packed
yöntemini çağırırız.
// my-dot-product.wgsl
@compute @workgroup_size(64)
fn main(@builtin(global_invocation_id) gid : vec3u) {
var sum : f32;
let start = gid.x * uniforms.dim;
for (var i = 0u; i < uniforms.dim; i++) {
let v1 : u32 = vector.values[i];
let v2 : u32 = matrix.values[start + i];
sum += dot4U8Packed(v1, v2);
}
}
Hem 16 bit kayan nokta hem de paketlenmiş tam sayı nokta ürünleri, Chrome'da AI ve makine öğrenimini hızlandıran özelliklerdir. 16 bit kayan nokta, donanım tarafından desteklendiğinde kullanılabilir ve Chrome, paketlenmiş tam sayılarla çalışan nokta ürünlerini tüm cihazlara uygular.
Daha iyi performans elde etmek için şu anda Chrome'un Kararlı sürümünde bu özellikleri kullanabilirsiniz.
Önerilen özellikler
Gelecekte, iki özelliği daha araştırıyoruz: alt gruplar ve işbirlikli matris çarpım.
Alt gruplar özelliği, iletişim kurmak veya 16'dan fazla sayının toplamı gibi toplu matematik işlemleri gerçekleştirmek için SIMD düzeyinde paralellik sağlar. Bu, iş parçacıkları arasında verimli bir veri paylaşımına olanak tanır. Alt gruplar, farklı adlara ve biraz farklı biçimlere sahip modern GPU API'lerinde desteklenir.
Ortak grubu, WebGPU standartlaştırma grubuna aldığımız bir teklife dönüştürdük. Ayrıca, deneysel bir işareti kullanarak Chrome'da alt grupların prototipini oluşturduk ve ilk sonuçlarımızı tartışmaya sunduk. Asıl sorun, taşınabilir davranışın nasıl sağlanacağıdır.
İşbirlikli matris çarpım, GPU'lara yeni eklenen bir özelliktir. Büyük matris çarpımları, daha küçük matris çarpımlarına bölünebilir. Kooperatif matris çarpım, tek bir mantıksal adımda bu daha küçük sabit boyutlu bloklarla çarpma işlemleri yapar. Bu adımda, bir ileti dizisi grubu sonucu hesaplamak için verimli bir şekilde işbirliği yapar.
Temel GPU API'lerine yönelik desteği inceledik ve WebGPU standartlaştırma grubuna bir teklif sunmayı planlıyoruz. Alt gruplarda olduğu gibi, tartışmanın büyük bir kısmının taşınabilirlik etrafında olmasını bekliyoruz.
Alt grup işlemlerinin performansını değerlendirmek amacıyla, gerçek bir uygulamada alt gruplara yönelik deneysel desteği MediaPipe'e entegre ettik ve bunu alt grup işlemleri için Chrome prototipiyle test ettik.
Büyük dil modelinin önceden doldurma aşamasının GPU çekirdeklerinde alt gruplar kullandık. Bu nedenle yalnızca önceden doldurma aşamasının hızlandırılmasını raporluyorum. Intel GPU'da alt grupların referans değere göre iki buçuk kat daha hızlı performans gösterdiğini görüyoruz. Ancak bu iyileştirmeler farklı GPU'larda tutarlı değil.
![MediaPipe LLM çıkarımındaki alt grupların hızlandırılmasının ekran görüntüsü](https://developer.chrome.com/static/blog/io24-webassembly-webgpu-2/image/subgroups-start.jpeg?authuser=19&hl=tr)
Sonraki grafikte, birden fazla tüketici GPU'su genelinde matris çarpım mikro karşılaştırmasını optimize etmek için alt gruplar uygulamanın sonuçları gösterilmektedir. Matris çarpımları, büyük dil modellerinde daha ağır işlemlerden biridir. Veriler, GPU'ların çoğunda alt grupların hızı iki, beş, hatta referansın on üç katı artırdığını gösteriyor. Ancak ilk GPU'da, alt grupların hiç olmadığı kadar iyi olduğuna dikkat edin.
![Matris çarpım işlemi için alt grup hızlandırma ekran görüntüsü](https://developer.chrome.com/static/blog/io24-webassembly-webgpu-2/image/subgroups-speedup-matrix-multiply.jpeg?authuser=19&hl=tr)
GPU optimizasyonu zor
Sonuç olarak, GPU'nuzu optimize etmenin en iyi yolu, istemcinin sunduğu GPU'ya bağlıdır. İşin içine birçok karmaşık faktör uygulanabileceğinden, yeni GPU özelliklerini kullanmak her zaman beklediğiniz gibi sonuç vermeyebilir. Bir GPU'da en iyi optimizasyon stratejisi, başka bir GPU'da en iyi strateji olmayabilir.
GPU'nun bilgi işlem iş parçacıklarını tam olarak kullanırken bellek bant genişliğini en aza indirmek istiyorsanız.
Bellek erişim kalıpları da gerçekten önemli olabilir. İşlem iş parçacıkları, donanıma en uygun kalıpla belleğe eriştiğinde GPU'lar çok daha iyi performans gösterir. Önemli: Farklı GPU donanımlarında farklı performans özellikleri beklemeniz gerekir. GPU'ya bağlı olarak farklı optimizasyonlar çalıştırmanız gerekebilir.
Aşağıdaki grafikte, aynı matris çarpım algoritmasını aldık ancak çeşitli optimizasyon stratejilerinin etkisini ve farklı GPU'lar arasındaki karmaşıklığı ve varyansı daha iyi göstermek için başka bir boyut ekledik. Burada, "Swizzle" adını verdiğimiz yeni bir teknik geliştirdik. Swizzle, bellek erişim kalıplarını donanım için daha optimum olacak şekilde optimize eder.
Gördüğünüz üzere hafızadaki hızlı hareket, büyük bir etki yaratıyor. bu bazen alt gruplardan bile daha etkili olabiliyor. GPU 6'da swizzle hızlanma 12 kat, alt gruplar ise 13 kat hızlanma sağlar. İkisi de toplamda 26 kat gibi inanılmaz bir hıza sahip. Diğer GPU'larda, bazen swizzle ve alt gruplar tek başına olduğundan daha iyi performans gösterir. Diğer GPU'larda ise yalnızca swizzle kullanımı en iyi performansı gösterir.
![Matris çarpım stratejileri için hızlandırma ekran görüntüsü](https://developer.chrome.com/static/blog/io24-webassembly-webgpu-2/image/subgroups-speedup-strategies.jpeg?authuser=19&hl=tr)
GPU algoritmalarını her donanımda iyi çalışacak şekilde ayarlamak ve optimize etmek büyük bir uzmanlık gerektirebilir. Ancak neyse ki Mediapipe, Transformers.js, Apache TVM, ONNX Runtime Web gibi daha üst düzey kitaplık çerçevelerine yönelik çok sayıda yetenekli çalışma var.
Kitaplıklar ve çerçeveler, çeşitli GPU mimarilerini yönetmenin ve istemcide iyi çalışacak platforma özgü kod oluşturmanın karmaşıklığını yönetmek için uygun konuma sahiptir.
Çıkarımlar
Chrome ekibi, makine öğrenimi iş yükleri için web platformunu iyileştirmek amacıyla WebAssembly ve WebGPU standartlarının iyileştirilmesine yardımcı olmaya devam etmektedir. Daha hızlı işlem bileşenlerine, web standartlarında daha iyi birlikte çalışabilirliğe ve hem büyük hem de küçük modellerin cihazlar arasında verimli bir şekilde çalışabilmesine yatırım yapıyoruz.
Amacımız, platformun özelliklerini en üst düzeye çıkarırken web'in en iyi özelliklerini (ör. erişim, kullanılabilirlik ve taşınabilirlik) korumaktır. Bunu tek başımıza da yapmıyoruz. W3C'deki diğer tarayıcı tedarikçileri ve çok sayıda geliştirme iş ortağıyla birlikte çalışıyoruz.
WebAssembly ve WebGPU ile çalışırken aşağıdakileri hatırlayacağınızı umuyoruz:
- Yapay zeka çıkarımı artık web'de cihazlar arasında kullanılabilir. Bu, istemci cihazlarda çalışma avantajını sunar (ör. sunucu maliyetinde azalma, düşük gecikme süresi ve daha fazla gizlilik).
- Ele alınan pek çok özellik öncelikle çerçeve yazarlarıyla alakalı olsa da uygulamalarınız fazla yük olmadan fayda sağlar.
- Web standartları esnek ve sürekli gelişiyor. Her zaman geri bildirim istiyoruz. WebAssembly ve WebGPU için kendi analizlerinizi paylaşın.
Teşekkür
WebGPU f16 ve paketlenmiş tam sayı nokta ürün özelliklerinin geliştirilmesinde büyük rol oynayan Intel web grafik ekibine teşekkür ederiz. W3C'deki WebAssembly ve WebGPU çalışma gruplarının diğer üyelerine, diğer tarayıcı tedarikçileri de dahil olmak üzere teşekkür ediyoruz.
Hem Google'daki hem de açık kaynak topluluğundaki yapay zeka ve makine öğrenimi ekiplerine muhteşem iş ortakları oldukları için teşekkür ederiz. Tabii tüm bunları mümkün kılan tüm ekip arkadaşlarımız.