NVIDIA cuPyNumeric ile NumPy’yi Laptoplardan Süper Bilgisayarlara Kolayca Ölçeklendirin

Python, veri bilimi, makine öğrenimi ve sayısal hesaplamalar için en yaygın programlama dilidir. Bilim insanları ve araştırmacılar arasında popülaritesini artırmaya devam etmektedir. Python ekosysteminde, NumPy, dizi tabanlı sayısal hesaplamalar yapmak için temel olan Python kütüphanesidir.

NumPy’nin standart uygulaması, yalnızca sınırlı bir dizi işlem üzerinde çoklu çekirdekler arasında paralel çalışırken, genellikle tek bir CPU çekirdeği üzerinde çalışır. Bu tek iş parçacıklı, yalnızca CPU destekli yürütme, işlenebilecek veri ölçeğini ve hesaplamaların hızını kısıtlamaktadır.

GPU hızlandırmalı NumPy uygulamaları mevcut olsa da, bu uygulamalara dayalı kodu çok sayıda GPU veya düğüm üzerinde ölçeklendirmek, genellikle manuel veri bölme, senkronizasyon ve dağıtım için kapsamlı kod değişiklikleri gerektirir. Bu tür kod değişiklikleri işlevsel olarak doğru ve verimli olmak açısından karmaşık ve zaman alıcı olabilir.

Ayrıca, dağıtılmış programlama konusunda az tecrübeye sahip olan alan bilim insanları, bu değişikliklerin yapılması için genellikle bilgisayar bilimi uzmanlarıyla iş birliği yapmaktadır, bu da deneyleme ve araştırmayı doğrulama süreçlerini yavaşlatmaktadır.

cuPyNumeric Nedir?

Bu verimlilik sorununu çözmek amacıyla, NVIDIA cuPyNumeric adında, NumPy API’sinin açık kaynaklı, dağıtılmış ve hızlandırılmış bir uygulamasını geliştirdik. cuPyNumeric, bilim insanları, araştırmacılar ve büyük ölçekli problemlerle çalışanların, NumPy programlarını orta ölçekli veri kümeleri üzerinde geliştirip test etmelerine olanak tanır. Bu programlar, hiçbir kod değişikliği olmadan, süper bilgisayarlar veya bulut üzerinden devasa veri kümelerine kolayca ölçeklenebilir.

cuPyNumeric, hızlı bir şekilde NumPy‘nın verimliliğini ve GPU hızlandırmanın performans avantajlarını bir araya getirir. cuPyNumeric, yerinde güncellemeler, yayılma ve kapsamlı indeksleme anlamları gibi temel NumPy özelliklerini destekler.

cuPyNumeric ile Başlangıç

cuPyNumeric kullanmaya başlamak için, bir NumPy programında numpy yerine cupynumeric kütüphanesini içe aktarmanız yeterlidir. Aşağıdaki örnek, NumPy API’lerini kullanarak pi sayısını tahmin etmektedir:

 
# numpy olarak np'yi içe aktar
import cupynumeric as np

num_points = 1000000000

# Alanı 4 olan bir karede rastgele noktalar üret
x = np.random.uniform(-1, 1, size=num_points)
y = np.random.uniform(-1, 1, size=num_points)

# Bir birimlik bir çember içine düşen noktaların olasılığını hesapla
probability_in_circle = np.sum((x ** 2 + y ** 2) 

Program, cuPyNumeric veya NumPy ile çalıştırıldığında, kesin değeri farklı olsa da aşağıdaki çıktıyı üretir:

PI sayısı 3.141572908

Sadece içe aktarma ifadesindeki basit bir değişiklikle, bu kod artık herhangi bir makinede ölçeklenmeye hazırdır:

  • GPU olmayan dizüstü bilgisayarlarda, kod mevcut CPU çekirdeklerini kullanarak paralel çalıştırılır.
  • Birden fazla GPU’ya sahip bir sistemde, aynı kod çoklu GPU’larla daha hızlı çalışır.
  • Bu kod, bir süper bilgisayarda da herhangi bir kod değişikliği olmadan çalıştırılabilir; ancak kodun böyle güçlü bir makineden en iyi şekilde faydalanmak için yeterli hesaplama gücü yoktur.

cuPyNumeric ile Stencil Örneği

cuPyNumeric’in avantajlarını gösteren daha ilginç bir örnek de stencil hesaplamalarıdır. Stencil programları, bilimsel hesaplamalar için en yaygın algoritma türlerinden biridir. Stencil programları, genellikle ilk oluşturan hücrelerle komşu hücrelerin kesişimini gösteren dilimler aracılığıyla NumPy’de doğal olarak ifade edilir.

Ancak, bu programlar çoklu GPU sistemleri için her zaman kolayca paralel hale getirilemez, çünkü bir GPU tarafından merkez hücrelerde yapılan herhangi bir değişiklik, diziler çoklu GPU’lar arasında bölündüğünde diğer GPU’lara aktarılmalıdır.

cuPyNumeric, saf NumPy ile yazılmış stencil kodunu, programcıyı bu dağıtımla ilgili düşünmeye zorlamadan her türlü GPU veya düğümde otomatik olarak ölçeklendirir.

Aşağıdaki örnek kod, bir 2D dizi oluşturur ve her hücre için 5 noktalı bir stencil hesabı yapar:

import cupynumeric as np

grid = np.random.rand(N+2, N+2)
# Dizi üzerinde çoklu görünüm oluştur.
center = grid[1:-1, 1:-1]
north  = grid[0:-2, 1:-1]
east   = grid[1:-1, 2:]
west   = grid[1:-1, 0:-2]
south  = grid[2:, 1:-1]
for _ in range(niters):
  average = (center + north + east + west + south) * 0.2
  center[:] = average

Bu program çoklu GPU’larda çalıştırıldığında, diziler otomatik olarak makineler üzerindeki GPU’lar arasında parça parça dağıtılır ve her GPU, yerel veriler üzerinde işlemi gerçekleştirir.

Data ve hesaplama dağıtımının yanı sıra, cuPyNumeric, grid dizisinin aliasing görüntüleri arasındaki iletişimi otomatik olarak çıkarır. center[:] = average işlemi sonrasında, center dizisindeki güncellemelerin north, east, west ve south dizilerine aktarılması gereklidir.

cuPyNumeric, bu iletişimi, programda herhangi bir açık iletişim kodu olmadan gerçekleştirir ve yalnızca her bir parçanın kenarlarındaki verilerin iletilmesi gerekebileceği halo benzeri bir iletişim modelini otomatik olarak keşfeder. Bu şekilde, cuPyNumeric, benzer alanları ve dağıtılmış dizilerin mutasyonunu destekleyen tek mevcut dağıtılmış NumPy uygulamasıdır.

cuPyNumeric ile NumPy Operasyonlarını Paralelleştirme

cuPyNumeric, tasarımı gereği, NumPy API’lerinin vektör tabanlı işlemler etrafında inşa edildiği gerçeğinden yararlanarak, dizileri bölümlere ayırır ve her bir alt küme üzerinde çoklu GPU’larda paralel hesaplamalar gerçekleştirir. Bu sırada, cuPyNumeric, GPU’ların aynı dizilerin alt kümelerine çakışan erişim yapması durumunda gerekli iletişimi sağlar.

cuPyNumeric, stencil örneği ile NumPy operasyonlarını nasıl paralelleştirdiğini şu şekilde gösterir:

center + north ifadesi alındığında, bu işlemi birden çok GPU’da paralel olarak gerçekleştirmek için cuPyNumeric, center ve north dizilerini GPU’lar arasında şu şekilde dağıtır: Eğer bir GPU’nun center dizisi bir bölümü center[i,j] içeriyorsa, aynı GPU’daki north dizisinin karşılık gelen bölümü de north[i,j] olmalıdır.

Diziler bölümlere ayrıldığında, cuPyNumeric GPU’larda görevler başlatır. Her GPU üzerindeki görev, o GPU’ya atanan center ve north dizisinin parçaları üzerinde eleman bazında toplama işlemi yapar. Sonuçta, bütün işlemler daha verimli ve hızlandırılmış bir şekilde ilerler.

Gerçek Dünyada Geliştirici Verimliliği

Stencil örneği küçük ve basit bir program olmasına rağmen, büyük bilimsel uygulamaların cuPyNumeric’e taşınmasında başarı sağladık. Örneğin, TorchSWE, Pi-Yueh Chuang ve Dr. Lorena Barba tarafından geliştirilen GPU hızlandırmalı bir sığ su denklemleri çözücüsüdür. TorchSWE, dikey olarak ortalama Navier-Stokes denklemlerini çözüp, nehirler, kanallar ve kıyı alanlarında serbest yüzey su akışını simüle eder ve sel sularının haritalanmasında yardım eder.

Yüksek çözünürlüklü sayısal simülasyonlar, yüz milyonlarca veri noktası gerektirir ve dağıtılmış hesaplama gerektirir. Orijinal TorchSWE uygulaması, problemi manuel olarak parçalara ayırarak iletişimi ve eşzamanlamayı yönetmektedir.

cuPyNumeric, TorchSWE’nin dağıtılmış bir uygulamasını, MPI uygulamasının karmaşıklıklarını ortadan kaldırarak mümkün kıldığı için çok büyük bir kolaylık sağlamaktadır. TorchSWE, cuPyNumeric’e geçirildiğinde, tüm alan ayrıştırma mantığı çıkarıldı ve başka bir kod değişikliği olmadan kolayca çoklu GPU ve düğümler üzerinde ölçeklendirildi. Bu ölçeklenebilirlik, araştırmacılara kritik bilimsel problemleri ele alabilme olanağı sundu.

cuPyNumeric uygulaması, %20 daha az kod çıkararak, alan bilimcileri için dağıtılmış yürütme gerektiren karmaşık mantığı anlamak ve uygulamak zorunda kalmadan geliştirme ve bakım süreçlerini basitleştirdi.

Nasıl Başlanır?

cuPyNumeric’i indirmek için en kolay yol, conda kullanmaktır:

 
$ conda install -c conda-forge -c legate cupynumeric

Daha fazla bilgi için aşağıdaki kaynaklara göz atabilirsiniz:

cuPyNumeric ile ilgili daha fazla örnek için, Örnekler kısmına göz atabilirsiniz. Ayrıca, Bölüm X: cuPyNumeric ile Dağıtılmış Hesaplama başlıklı kendi kendine rehberli bir eğitim alabilirsiniz.

cuPyNumeric, NumPy programlarının kod değişikliği gerektirmeden ölçeklenmesini sağlasa da, her NumPy programı etkin bir şekilde ölçeklenemez. cuPyNumeric ile ölçeklenebilir performans hakkında daha fazla bilgi ve performansı olumsuz etkileyebilecek yaygın anti-paternlere dair daha fazla bilgiye ulaşmak için En İyi Uygulamalar kısmını inceleyebilirsiniz.

Sonuç

Bu yazıda NVIDIA cuPyNumeric’i tanıttık; hızlandırılmış ve dağıtılmış bir NumPy yerine geçebilecek bir çözüm. cuPyNumeric ile NumPy programlarının dizüstü bilgisayarlardan süper bilgisayarlara kadar geniş bir yelpazede ölçeklendirilmesi artık yalnızca bir içe aktarma bildirimi ile mümkündür. Ayrıca, cuPyNumeric’in multi-GPU yürütmesi için NumPy işlemlerini nasıl paralelleştirdiğini bir stencil örneği ile gösterdik.

Herhangi bir yorum veya soru için, lütfen ekiple /nv-legate/discussion GitHub repo sayfası üzerinden ya da e-posta ile iletişime geçin.

Kaynak

Nvdia Blog

Exit mobile version