Dask ile RAPIDS Kullanarak Çoklu GPU ile Veri Analizi için En İyi Uygulamalar

Gelişen teknolojiyle birlikte, giderek daha yoğun bir hesaplama altyapısına geçiyoruz. Daha fazla işlem gücü, daha fazla GPU ve hızlandırılmış ağ iletişimi ile birlikte, çoklu GPU ile eğitim ve analiz, sürekli popülerlik kazanıyor. Bu geçişte, geliştiricilerin ve uzmanların CPU’dan GPU kümelerine geçerken ihtiyaç duyacağı araçlar ve en iyi uygulamalar büyük önem taşıyor. RAPIDS, GPU ile hızlandırılmış veri bilimi ve AI kütüphanelerinden oluşan bir açık kaynak yazılım setidir. Bu kütüphaneler, Spark ve Dask gibi araçlar sayesinde, daha büyük iş yükleri için kolayca ölçeklenebilir. Bu blog yazısı, RAPIDS Dask’ın kısa bir incelemesini sağlar ve çoklu GPU veri analizi için üç en iyi uygulamayı vurgular.

GPU’ları maksimum performansla kullanmak isteyen kullanıcılar, genellikle bellek baskısı ve istikrar sorunları ile karşılaşır. GPU’lar, CPU’lardan daha güçlü hesaplama yeteneklerine sahip olsalar da genellikle sistem belleğinden daha az belleğe sahiptir. Örneğin, GPU iş yükleri çoğunlukla, GPU belleğinin iş yükünü bir seferde işlemek için gereken toplam bellek miktarından daha küçük olduğu dış bellek senaryolarında çalıştırılır. Ayrıca, CUDA ekosistemi, çeşitli amaçlara ve uygulamalara hizmet eden birçok bellek türü sunmaktadır.

Dask Nedir?

Dask, dağıtık Python için açık kaynaklı, son derece esnek bir kütüphanedir. Dask, karmaşık özel Python kodunu ölçeklendirmeye yardımcı olur, ancak en önemlisi, Dask-Array ve Dask-Dataframe ile dizi ve veri çerçevesi iş yüklerini ölçeklendirmeye yardımcı olabilir. RAPIDS, GPU ETL ve ML iş yüklerini ölçeklendirmek için Dask-DataFrame kullanmaktadır; bu sayede Dask-cuDF ve cuML/XGBoost ile Pandas benzeri bir arayüz sağlar.

df = dd.read_parquet("/my/parquet/dataset/")
agg = df.groupby('B').sum()
agg.compute()

Dask ile CPU ve GPU için En İyi Uygulamalar

Dask’ın birçok avantajından biri, kullanıcıların hem CPU hem de GPU arka uçlarını hedefleyebilmesidir. Ancak, bir CPU ve bir GPU için ayrı kod tabanları geliştirmek zaman alıcı ve bakım açısından zorlayıcıdır. Dask, kolayca CPU ve GPU arka uçları arasında geçiş yapmayı destekler.

Örneğin, PyTorch’un cihaz yapılandırma mekanizmasına benzer bir yöntemle:

device = ‘cuda’ if torch.cuda.is_available() else ‘cpu’ 

Dask da arka uç hedefini yapılandırabilir:

# GPU Arka Uçları
dask.config.set({"array.backend": "cupy"})
dask.config.set({"dataframe.backend": "cudf"})

# CPU Arka Uçları
dask.config.set({"array.backend": "numpy"})
dask.config.set({"dataframe.backend": "pandas"})

# Çevresel Değişkenler ile Yapılandırma
DASK_DATAFRAME__BACKEND=cudf

Artık, belirli arka uç I/O direktifleri çağırmadan ve donanımdan bağımsız bir şekilde dağıtılmış Python analiz kodu yazabiliyoruz:

# Veri Çerçevesi Örneği  
dask.config.set({"dataframe.backend": "cudf"}):     
    ddf = dd.read_parquet('example.parquet')     
    res = ddf.groupby("col").agg({'stats': ['sum', 'min', 'mean']})
    res.compute()

Bu kolay CPU/GPU ayarını kullanarak, Dask-RAPIDS kullanıcıları, herhangi bir geliştirme yükü olmadan her iki cihaz için de kolayca geliştirme yapabilir. Daha kapsamlı bir örnek olarak, NeMo içindeki veri düzenleme çerçevesi, bu mekanizmayı kullanarak CPU/GPU dağıtımlarını sağlıyor.

Küme ve Bellek Yapılandırması

Veri iş akışları, hem hesaplama hem de bellek açısından yoğun uygulamalardır. Dağıtık uygulamaların belleği nasıl kullandığını yapılandırmak ve yönetmek, bir işin tamamlanması ile başarısız olması arasında fark yaratabilir. “Doğru” belleği kullanmamak, iş akışlarının performans kaybına veya bellek yetersizliği (OOM) hatalarına neden olabilir. Doğru belleği seçmek ve dağıtık sistemleri yapılandırmak zorlayıcı olabilir; bu genellikle yüksek düzeyde uzmanlık gerektirir ve zaman alıcı kıyaslamalar yapmayı da içerebilir. Yapılan birçok deneme sonucunda, çeşitli tablolara dayalı iş yükleri – örneğin ETL (filtreler, join’ler, toplamalar vb.) ve çoğaltma (NeMo Curator) – için iyi bir başlangıç yapılandırması bulduk:

dask cuda worker  --rmm-async  --rmm-pool-size   --enable-cudf-spill 

RMM seçeneklerini kullanmak: `rmm-async` ve `rmm-pool-size`, performansı ve istikrarı önemli ölçüde artırabilir.

`rmm-async`, temel cudaMallocAsync bellek ayırıcı kullanır ve bu, bellek parçalanmasını büyük ölçüde azaltır; bu, küçük bir veya ihmal edilebilir performans kaybı ile gerçekleştirilir. Bellek parçalanması OOM hatalarına kolayca yol açabilir. Derinlemesine inceleme için, CUDA Stream Ordered Memory Allocator blog serisinin 1. ve 2. bölümlerine göz atılabilir.

`rmm-pool-size` parametresi, GPU üzerinde bir bellek havuzu ön ayırır. Ön ayırma ile bellek alt tahsisleri yapmak, doğrudan CUDA tahsislerinde (raw cudaMalloc) çok daha hızlıdır. Bunun nedeni, GPU bellek tahsislerinin ve serbest bırakılmasının oldukça maliyetli olmasıdır ve veri uygulamalarında, bir iş akışında yapılması gereken çok sayıda tahsis/serbest bırakma çağrısı vardır; bunlar toplamda performansı olumsuz etkileyebilir.

Ayrıca, cihazdan ana bilgisayara veri taşımak, yani `spill` etmek sadece bir özellik olarak uygulanmaz. Spill işlemi genel olarak uygulanabilir, ancak genellikle performans kaybına yol açar. Dask-CUDA ve cuDF, birkaç spill mekanizması sunmaktadır: `device-memory-limit`, `memory-limit`, `jit-unspill`, `enable-cudf-spill`. `enable-cudf-spill` ise cuDF’nin dahili ana bellek spilling yeteneğini aktif hale getirir. CuDF’nin iç spilling mekanizması, nesnelerin veya aramaların, GPU’da mevcut olan bellek miktarından fazlasını gerektirdiği durumlarda, verileri (cuDF tamponları) cihazdan ana belleğe taşır. Tablo tabanlı iş yükleri için, `enable-cudf-spill` kullanımının, diğer Dask-CUDA seçeneklerine göre, genellikle daha hızlı ve daha stabil olduğunu bulduk.

Hızlandırılmış Ağ İletişimi

Daha önce bahsettiğimiz gibi, yoğun çoklu GPU sistemleri, NVLink kullanarak hızlandırılmış ağ iletişimi ile tasarlanmıştır. Grace Blackwell ve en son NVLink, çift yönlü 900 GB/s bant genişliğine erişim sağlar. Yaygın ETL işlemleri, join’ler, shuffle işlemleri gibi, veri taşımayı gerektirir; bu nedenle, CPU ve GPU arasında spill etmek, dış bellek algoritmaları için kritik öneme sahiptir. Bu yoğun sistemlerde NVLink kullanmak, en yüksek performansı elde etmek için çok önemlidir. Dask’ta bu donanım sistemleri UCX etkinleştirilerek kolayca devreye alınabilir:

# Tek Düğüm Kümesi
cluster = LocalCUDACluster(protocol="ucx")

# CLI
dask-cuda-worker  --protocol ucx

Sonuç

Dask CUDA işçilerinin optimal bellek ayarları ile yapılandırılması ve UCX ile hızlandırılmış ağın etkinleştirilmesi sayesinde, kullanıcılar hem kararlı dış bellek GPU hesaplama hem de maksimum performansa ulaşabilir. Ayrıca, CPU ve GPU gibi çoklu donanım arka uçlarını hedeflemek, Dask’ın dizi ve veri çerçevesi arka uç seçenekleri kullanılarak kolayca gerçekleştirilebilir.

Dask RAPIDS’i en iyi şekilde kullanmanın belgeleri ve ilave ayrıntıları için, Dask-cuDF ve Dask-CUDA En İyi Uygulamalar belgelerini okumanızı öneririz.

Kaynak

Nvdia Blog

Exit mobile version