Bu makalede, GPU'ların Grafik, Sinir Ağları ve Derin Öğrenme görevlerinde neden iyi olduğunu ve CPU'ların çok sayıda sıralı, karmaşık genel amaçlı bilgi işlem görevlerinde neden iyi olduğunu anlamak için bazı temel düşük seviyeli ayrıntıları inceleyeceğiz. Bu yazı için araştırmam ve biraz daha ayrıntılı bilgi edinmem gereken birkaç konu vardı, bunlardan bazılarına sadece geçerken değineceğim. Yalnızca CPU ve GPU işlemenin mutlak temellerine odaklanmak için kasıtlı olarak yapılır.
Daha önceki bilgisayarlar özel cihazlardı. Donanım devreleri ve mantık kapıları belirli bir dizi şeyi yapacak şekilde programlandı. Yeni bir şey yapılması gerekiyorsa devrelerin yeniden kablolanması gerekiyordu. "Yeni bir şey" iki farklı denklem için matematiksel hesaplamalar yapmak kadar basit olabilir. İkinci Dünya Savaşı sırasında Alan Turing, Enigma makinesini yenecek programlanabilir bir makine üzerinde çalışıyordu ve daha sonra "Turing Makinesi" makalesini yayınladı. Aynı sıralarda John von Neumann ve diğer araştırmacılar da temelde şunu öneren bir fikir üzerinde çalışıyorlardı:
Bilgisayarımızdaki her şeyin ikili olduğunu biliyoruz. Dize, görüntü, video, ses, işletim sistemi, uygulama programı vb. hepsi 1'ler ve 0'lar olarak temsil edilir. CPU mimarisi (RISC, CISC, vb.) spesifikasyonları, CPU üreticilerinin uyması gereken ve işletim sisteminin donanımla arayüz oluşturması için mevcut olan talimat setlerine (x86, x86-64, ARM, vb.) sahiptir.
Verileri içeren işletim sistemi ve uygulama programları, CPU'da işlenmek üzere talimat setlerine ve ikili verilere çevrilir. Çip seviyesinde işlem transistörlerde ve mantık kapılarında yapılır. İki sayıyı toplamak için bir program çalıştırırsanız, toplama ("işleme") işlemcideki bir mantık kapısında yapılır.
CPU'da Von Neumann mimarisine göre iki sayıyı toplarken devredeki iki sayı üzerinde tek bir toplama komutu çalışır. Bu milisaniyenin çok küçük bir kısmı boyunca, işlem ünitesinin (yürütme) çekirdeğinde yalnızca ekleme talimatı yürütüldü! Bu detay beni her zaman etkilemiştir.
Yukarıdaki diyagramdaki bileşenler apaçık ortadadır. Daha fazla ayrıntı ve ayrıntılı açıklama için bu mükemmel makaleye bakın. Modern CPU'larda, tek bir fiziksel çekirdek birden fazla tamsayı ALU, kayan noktalı ALU vb. içerebilir. Yine bu birimler fiziksel mantık kapılarıdır.
GPU'yu daha iyi anlayabilmek için CPU çekirdeğindeki 'Donanım Konusunu' anlamamız gerekiyor. Donanım iş parçacığı, her bir CPU saat döngüsünde bir CPU çekirdeğinin yürütme birimlerinde yapılabilen bir bilgi işlem birimidir . Bir çekirdekte gerçekleştirilebilecek en küçük iş birimini temsil eder.
Yukarıdaki diyagram CPU komut döngüsünü/makine döngüsünü göstermektedir. CPU'nun tek bir talimatı yürütmek için gerçekleştirdiği bir dizi adımdır (örneğin: c=a+b).
Getirme: Program sayacı (CPU çekirdeğindeki özel kayıt) hangi talimatın getirilmesi gerektiğini takip eder. Talimat alınır ve talimat kaydında saklanır. Basit işlemler için ilgili veriler de alınır.
Kod Çözme: Operatörleri ve işlenenleri görmek için talimatın kodu çözülür.
Yürütme: Belirtilen işleme göre uygun işlem birimi seçilir ve yürütülür.
Bellek Erişimi: Bir talimat karmaşıksa veya ek veri gerekiyorsa (birkaç faktör buna neden olabilir), belleğe erişim yürütmeden önce yapılır. (Basitlik açısından yukarıdaki şemada göz ardı edilmiştir). Karmaşık bir talimat için, ilk veriler hesaplama ünitesinin veri kaydında mevcut olacaktır, ancak talimatın tam olarak yürütülmesi için L1 ve L2 önbelleğinden veri erişimi gereklidir. Bu, hesaplama biriminin yürütülmesinden önce küçük bir bekleme süresi olabileceği ve bekleme süresi boyunca donanım iş parçacığının hala hesaplama birimini tuttuğu anlamına gelir.
Geri Yaz: Eğer yürütme çıktı üretirse (örneğin: c=a+b), çıktı kayıt/önbellek/belleğe geri yazılır. (Yukarıdaki diyagramda veya yazının sonraki herhangi bir yerinde basitlik açısından göz ardı edilmiştir)
Yukarıdaki diyagramda hesaplama yalnızca t2'de yapılıyor. Geri kalan zamanlarda çekirdek boşta kalıyor (hiçbir iş yapmıyoruz).
Modern CPU'lar, temel olarak (getirme-kod çözme-yürütme) adımların saat döngüsü başına eş zamanlı olarak gerçekleşmesini sağlayan HW bileşenlerine sahiptir.
Tek bir donanım iş parçacığı artık her saat döngüsünde hesaplama yapabilir. Buna talimat boru hattı denir.
Getirme, Kod Çözme, Bellek Erişimi ve Geri Yazma işlemleri CPU'daki diğer bileşenler tarafından gerçekleştirilir. Daha iyi bir kelime bulunamadığı için bunlara "boru hattı konuları" denir. Boru hattı iş parçacığı, bir talimat döngüsünün yürütme aşamasında olduğunda bir donanım iş parçacığı haline gelir.
Gördüğünüz gibi t2'den itibaren her döngüde hesaplama çıktısı alıyoruz. Daha önce her 3 döngüde bir hesaplama çıktısı alıyorduk. Ardışık düzen bilgi işlem verimini artırır. Bu, Von Neumann Mimarisindeki işleme darboğazlarını yönetme tekniklerinden biridir. Sıra dışı yürütme, dal tahmini, spekülatif yürütme vb. gibi başka optimizasyonlar da vardır.
Bu, GPU'lara geçmeden önce CPU hakkında tartışmak istediğim son kavramdır. Saat hızları arttıkça işlemciler de daha hızlı ve verimli hale geldi. Uygulama (komut seti) karmaşıklığının artmasıyla birlikte CPU hesaplama çekirdekleri gereğinden az kullanıldı ve bellek erişimini beklerken daha fazla zaman harcanıyordu.
Yani bir hafıza darboğazı görüyoruz. Hesaplama birimi belleğe erişim için zaman harcıyor ve herhangi bir yararlı iş yapmıyor. Bellek, CPU'dan birkaç sıra daha yavaştır ve bu fark yakın zamanda kapanmayacak. Buradaki fikir, tek bir CPU çekirdeğinin bazı birimlerindeki bellek bant genişliğini artırmak ve verileri, bellek erişimini beklerken hesaplama birimlerini kullanmaya hazır tutmaktı.
Hyper-threading, 2002 yılında Intel tarafından Xeon ve Pentium 4 işlemcilerde kullanıma sunuldu. Hyper-threading'den önce çekirdek başına yalnızca bir donanım iş parçacığı vardı. Hyper-threading ile çekirdek başına 2 donanım iş parçacığı olacaktır. Bu ne anlama geliyor? Bazı yazmaçlar, program sayacı, getirme birimi, kod çözme birimi vb. için kopya işleme devresi.
Yukarıdaki şema sadece hiper iş parçacıklı bir CPU çekirdeğindeki yeni devre elemanlarını göstermektedir. Tek bir fiziksel çekirdek bu şekilde İşletim Sistemine 2 çekirdek olarak görünür. Hyper-threading'in etkin olduğu 4 çekirdekli bir işlemciniz varsa, işletim sistemi tarafından 8 çekirdek olarak görülür . L1 - L3 önbellek boyutu, ek kayıtları barındıracak şekilde artacaktır. Yürütme birimlerinin paylaşıldığını unutmayın.
a=b+c, d=e+f yapan P1 ve P2 süreçlerimiz olduğunu varsayalım, bunlar HW iş parçacığı 1 ve 2 nedeniyle tek bir saat döngüsünde eş zamanlı olarak yürütülebilir. Tek bir HW iş parçacığıyla, daha önce gördüğümüz gibi, bu mümkün olmazdı. Burada, donanım iş parçacığı ekleyerek bir çekirdek içindeki bellek bant genişliğini artırıyoruz, böylece işlem birimi verimli bir şekilde kullanılabilir. Bu işlem eşzamanlılığını artırır.
Bazı ilginç senaryolar:
Bu makaleye göz atın ve ayrıca Colab not defterini deneyin. Matris çarpımının nasıl paralelleştirilebilir bir görev olduğunu ve paralel bilgi işlem çekirdeklerinin hesaplamayı nasıl hızlandırabileceğini gösteriyor.
Bilgi işlem gücü arttıkça grafik işlemeye olan talep de arttı. Kullanıcı arayüzü oluşturma ve oyun oynama gibi görevler paralel işlemler gerektirir ve bu da devre düzeyinde çok sayıda ALU ve FPU ihtiyacını artırır. Sıralı görevler için tasarlanan CPU'lar bu paralel iş yüklerini etkili bir şekilde işleyemedi. Böylece GPU'lar, grafik görevlerinde paralel işleme talebini karşılamak için geliştirildi ve daha sonra hızlandırılmış derin öğrenme algoritmalarında benimsenmelerinin yolu açıldı.
Şiddetle tavsiye ederim:
CPU'ların ve GPU'ların çekirdekleri, donanım iş parçacıkları, saat hızı, bellek bant genişliği ve çip üzerindeki belleği önemli ölçüde farklılık gösterir. Örnek:
Bu sayı GPU ile karşılaştırma yapmak için kullanılır, çünkü genel amaçlı bilgi işlemde en yüksek performansı elde etmek oldukça özneldir. Bu sayı teorik bir maksimum sınırdır, yani FP64 devreleri sonuna kadar kullanılmaktadır.
CPU'da gördüğümüz terminolojiler her zaman doğrudan GPU'lara çevrilmez. Burada bileşenleri ve çekirdek NVIDIA A100 GPU'yu göreceğiz. Bu makale için araştırma yaparken beni şaşırtan şey, CPU satıcılarının bir çekirdeğin yürütme birimlerinde kaç adet ALU, FPU vb. bulunduğunu yayınlamamalarıydı. NVIDIA çekirdek sayısı konusunda oldukça şeffaftır ve CUDA çerçevesi devre düzeyinde tam esneklik ve erişim sağlar.
Yukarıdaki diyagramda GPU'da L3 Önbelleğinin olmadığını, daha küçük L2 önbelleğini, daha küçük ama çok daha fazla kontrol ünitesi ve L1 önbelleğini ve çok sayıda işlem biriminin olduğunu görebiliriz.
Yukarıdaki diyagramlardaki GPU bileşenleri ve ilk anlamamız için bunların CPU eşdeğerleri aşağıda verilmiştir. CUDA programlaması yapmadım, bu yüzden onu CPU eşdeğerleriyle karşılaştırmak ilk başta anlamanıza yardımcı olur. CUDA programcıları bunu çok iyi anlıyorlar.
Grafikler ve derin öğrenme görevleri, SIM(D/T) [Tek talimat çoklu veri/iş parçacığı] tipi yürütmeyi gerektirir. yani tek bir talimat için büyük miktarlarda veriyi okumak ve bunlar üzerinde çalışmak.
CPU ve GPU'larda komut ardışık düzeni ve hiper iş parçacığının da yetenekleri olduğunu tartıştık. Uygulanma şekli ve çalışma şekli biraz farklıdır ancak prensipler aynıdır.
CPU'lardan farklı olarak GPU'lar (CUDA aracılığıyla), Pipeline Threads'e doğrudan erişim sağlar (bellekten veri getirir ve bellek bant genişliğini kullanır). GPU zamanlayıcıları ilk önce hesaplama birimlerini (ilişkili paylaşılan L1 önbelleği ve hesaplama işlenenlerini depolamak için kayıtlar dahil) doldurmaya çalışarak, ardından verileri kayıtlara ve HBM'ye getiren "boru hattı iş parçacıklarını" doldurmaya çalışarak çalışır. Tekrar vurgulamak isterim ki, CPU uygulama programcıları bu konuyu düşünmemektedir ve "boru hattı iş parçacıkları" ve çekirdek başına hesaplama birimi sayısı hakkındaki spesifikasyonlar yayınlanmamaktadır. Nvidia yalnızca bunları yayınlamakla kalmıyor, aynı zamanda programcılara tam kontrol sağlıyor.
Bunun ne kadar faydalı olduğunu görebileceğimiz CUDA programlama modeli ve model hizmet optimizasyon tekniğinde "toplama" hakkındaki özel bir yazıda bu konuyu daha ayrıntılı olarak ele alacağım.
Yukarıdaki diyagram CPU ve GPU çekirdeğindeki donanım iş parçacığının yürütülmesini göstermektedir. Daha önce CPU boru hattında tartıştığımız "bellek erişimi" bölümüne bakın. Bu diyagram bunu gösteriyor. CPU'nun karmaşık bellek yönetimi, bu bekleme süresini L1 önbelleğinden kayıtlara veri getirmeye yetecek kadar kısa (birkaç saat döngüsü) hale getirir. Verilerin L3'ten veya ana bellekten getirilmesi gerektiğinde, verileri zaten kayıtlı olan diğer iş parçacığı (bunu hiper iş parçacığı bölümünde gördük) yürütme birimlerinin kontrolünü alır.
GPU'larda, aşırı abonelik (çok sayıda ardışık düzen iş parçacığı ve kayıt) ve basit talimat seti nedeniyle, yürütmeyi bekleyen kayıtlarda büyük miktarda veri zaten mevcuttur. Yürütülmeyi bekleyen bu ardışık düzen iş parçacıkları, donanım iş parçacıkları haline gelir ve GPU'lardaki ardışık düzen iş parçacıkları hafif olduğundan, yürütmeyi her saat döngüsünde olduğu sıklıkta gerçekleştirir.
Gol üstü ne?
Daha küçük matrislerin matris çarpımındaki gecikmenin CPU ve GPU'da aşağı yukarı aynı olmasının ana nedeni budur. Denemek .
Görevlerin yeterince paralel olması ve verilerin, işlem FLOP'larını ve bellek bant genişliğini doyuracak kadar büyük olması gerekir. Tek bir görev yeterince büyük değilse, belleği doyurmak ve donanımdan tam olarak yararlanmak amacıyla hesaplama yapmak için bu tür birden fazla görevin paketlenmesi gerekir.
Hesaplama Yoğunluğu = FLOP / Bant Genişliği . yani, hesaplama birimlerinin saniyede yapabileceği iş miktarının, belleğin saniyede sağlayabildiği veri miktarına oranı.
Yukarıdaki şemada, daha yüksek gecikme süresine ve daha düşük bant genişliğine sahip belleğe gidildikçe hesaplama yoğunluğunun arttığını görüyoruz. Bilgi işlemin tam olarak kullanılabilmesi için bu sayının mümkün olduğu kadar küçük olmasını istiyoruz. Bunun için, hesaplamanın hızlı bir şekilde gerçekleşebilmesi için L1/Register'larda olabildiğince fazla veri tutmamız gerekiyor. HBM'den tek veri alırsak, buna değecek kadar tek veri üzerinde 100 işlem yaptığımız yalnızca birkaç işlem vardır. Eğer 100 işlem yapmazsak hesaplama birimleri boşta kalırdı. GPU'lardaki yüksek sayıda iş parçacığı ve kayıtların devreye girdiği yer burasıdır. İşlem yoğunluğunu düşük tutmak ve paralel çekirdekleri meşgul etmek için mümkün olduğu kadar veriyi L1/Kayıtlarda tutmak.
CUDA ve Tensor çekirdekleri arasında hesaplama yoğunluğu açısından 4X fark vardır çünkü CUDA çekirdekleri yalnızca bir 1x1 FP64 MMA yapabilirken Tensor çekirdekleri saat döngüsü başına 4x4 FP64 MMA talimatı yapabilir.
Yüksek sayıda hesaplama birimi (CUDA ve Tensor çekirdekleri), yüksek sayıda iş parçacığı ve kayıt (abonelik üzerinden), azaltılmış talimat seti, L3 önbellek yok, HBM (SRAM), basit ve yüksek verimli bellek erişim modeli (CPU'nun içerik değiştirmesiyle karşılaştırıldığında) , çok katmanlı önbellekleme, bellek sayfalama, TLB vb.), paralel hesaplamada (grafik oluşturma, derin öğrenme vb.) GPU'ları CPU'lardan çok daha iyi yapan ilkelerdir.
GPU'lar ilk olarak grafik işleme görevlerini yerine getirmek için oluşturuldu. Yapay zeka araştırmacıları CUDA'nın avantajlarından ve onun CUDA çekirdekleri aracılığıyla güçlü paralel işlemeye doğrudan erişiminden yararlanmaya başladı. NVIDIA GPU'da Doku İşleme, Işın İzleme, Raster, Polimorf motorlar vb. bulunur (grafiğe özel talimat setleri diyelim). Yapay zekanın benimsenmesinin artmasıyla birlikte, derin öğrenmeye adanmış 4x4 matris hesaplamasında (MMA talimatı) iyi olan Tensor çekirdekleri ekleniyor.
NVIDIA, 2017'den bu yana her mimarideki Tensor çekirdeği sayısını artırıyor. Ancak bu GPU'lar grafik işlemede de iyidir. GPU'larda talimat seti ve karmaşıklık çok daha az olmasına rağmen, tamamen derin öğrenmeye (özellikle Transformer Mimarisine) adanmış değildir.
Transformatör mimarisi için bir yazılım katmanı optimizasyonu (dikkat katmanının bellek erişim düzenine mekanik sempati) olan FlashAttention 2 , görevlerde 2 kat hızlanma sağlar.
CPU ve GPU'ya ilişkin derinlemesine ilk ilkelere dayalı anlayışımızla, Transformatör Hızlandırıcılarına olan ihtiyacı anlayabiliriz: Paralellik için çok sayıda hesaplama birimine sahip, azaltılmış komut seti içeren, özel bir çip (yalnızca transformatör işlemleri için devre), L1/L2 önbellekler, HBM'nin yerini alan devasa DRAM (kayıtlar), transformatör mimarisinin bellek erişim modeli için optimize edilmiş bellek birimleri. Sonuçta Yüksek Lisanslar (web ve mobilden sonra) insanlar için yeni yol arkadaşlarıdır ve verimlilik ve performans için özel çiplere ihtiyaç duyarlar.