cuDF’de JIT Derleme ile Verimli Dönüşümler

RAPIDS cuDF, GPU’lar ile veri işleme için geniş bir ETL algoritma seti sunar. Pandas kullanıcıları için, cudf.pandas çözümü ile cuDF hızlandırılmış algoritmalar sıfır kod değişikliği ile mevcuttur. C++ geliştiricileri ve ileri düzey kullanıcılar için, cuDF içindeki C++ alt modülü ile çalışmak, yeni işlevsellik ve performans seçenekleri sunar.

cuDF’nin C++ programlama modeli, girdi olarak sahiplenmeyen görünümleri kabul eder ve çıktı olarak sahiplenilen türler döndürür. Bu durum, GPU verilerinin ömrü ve sahipliği hakkında düşünmeyi kolaylaştırırken, cuDF API’lerinin bir araya getirilebilirliğini maksimize eder. Ancak bu modelin bir dezavantajı, bazı işlemlerin gereğinden fazla ara sonuçlar oluşturması ve aşırı GPU bellek transferlerine neden olmasıdır. Aşırı GPU bellek transferlerine bir çözüm olarak kernel birleşimi kullanılabilir; burada tek bir GPU çekirdeği aynı girdi verileri üzerinde birden fazla hesaplama gerçekleştirir.

Bu yazıda, JIT derlemesi ile kernel birleşiminin cuDF C++ programlama modeline nasıl getirildiği, daha yüksek veri işleme verimliliği ve daha etkili GPU bellek ve işlem kullanımı sağladığı açıklanmaktadır.

cuDF’de İfade Değerlendirmesi

Veri işleme alanında, ifadeler genellikle birer operand ve operatörler ağacı olarak temsil edilir; burada her yaprak düğüm bir sütun veya skalar, her kesişim ise bir operatördür. Tipik durumda, bir skalar ifade bir veya daha fazla girdiyi tek bir çıktı sütununa dönüştürür. Skalar ifadeler genellikle girdi ile çıktı arasındaki satır bazlı eşlemeleri temsil eder; her girdi satırı bir çıktı satırı üretir.

cuDF için aritmetik ifadelerin değerlendirilmesinde üç seçenek bulunmaktadır: önceden derlenmiş, AST (soyut sözdizimi ağaç) ve JIT dönüşümü.

Önceden derlenmiş yaklaşım, ifadenin her bir operatörü için libcudf kamu API’sını çağırarak, ağacı özyinelemeli olarak hesaplar. Bu yaklaşımın avantajı, libcudf’de en geniş veri türü ve operatör desteğine sahip olmasıdır. Bununla birlikte, ana dezavantajı, değerlendirmenin her aşamasında GPU global bellekte ara sonuçlar oluşturmasıdır.

AST yaklaşımı, tam ağacı parametre olarak alan compute_column API’sini kullanır ve sonra ağacı değerlendirmek için özel bir çekirdek kullanır. AST yürütmesi, GPU iş parçacığı başına satır paralelliği modeli kullanır. AST yorumlayıcı çekirdeği, cuDF’de kernel birleşimi için yararlı bir araçtır, ancak veri tipi ve operatör desteği konusunda sınırlamaları vardır.

cuDF’deki JIT dönüşümü, NVRTC kullanarak, belirli dönüşümleri tamamlamak için özel bir çekirdek oluşturur. NVRTC, özelleştirilmiş CUDA C++ çekirdeklerinin çalıştırma zamanı derlemesini sağlar ve deri birleşimlerini çalışma zamanında oluşturur. JIT derlemesinin avantajı, değerlendirilecek ifade için optimize edilmiş çekirdekler kullanmasıdır. Bu, derleyicinin GPU kaynaklarını verimli bir şekilde tahsis etmesini sağlar ve en kötü senaryo için aslında ayırmak zorunda kalınan GPU kayıtlarını gereksiz kılar.

JIT Dönüşümünü Kullanma

rapidsai/cudf GitHub deposu, hem önceden derlenmiş yaklaşımı hem de yeni JIT dönüşüm yaklaşımını kullanarak string_transforms örnekleri sunar. Örnek durumlar, string işlemi için kullanıcı tanımlı fonksiyonlar (UDF’ler) şeklinde hazırlanmıştır.

extract_email_jit JIT ve extract_email_precompiled örnekleri, bir girdi stringini alarak, stringin bir e-posta adresi olarak temel biçimlendirmesini doğruladıktan sonra, stringden e-posta sağlayıcısını çıkarmaya odaklanmıştır. Örneğin, user@provider.com gibi tipik bir e-posta adresi için hedef çıktı provider olacaktır. Kötü biçimlendirilmiş girdiler durumunda ise örnek “bilinmiyor” gibi alternatif bir giriş döndürmektedir.

Şekil 2, extract_email_precompiled örneğindeki mantığı göstermektedir. Yeşil renkle işaretlenmiş kısım “@” ve “.” noktasını belirlemekte, pembe renkle işaretlenmiş kısım is_valid alanını oluşturarak “@” ve “.” karakterlerinin varlığına ve konumuna dayanmaktadır. Son olarak, mavi renkte işaretlenmiş kısım, girdi stringlerinden sağlayıcıyı kesiştirirken, geçersiz giriş olduğu durumda alternatif girişi kopyalamaktadır. Bu yaklaşım doğru sonuçlar verir, ancak karakter pozisyonlarını, birden fazla Boolean sütunu ve alternatif girişi içeren sütunu oluşturmak için ekstra bellek ve işlem gücü kullanır.

JIT derleme kullanarak, aynı işlemi daha verimli bir şekilde gerçekleştiren bir GPU çekirdeği oluşturabilirsiniz. Şekil 3, extract_email_jit örneğini göstermekte olup, burada tanım dönüşümünü belirleyen ham bir string “udf” kullanılmaktadır. Bu süreç, “@” karakterinde bulma ve kesiştirme işlemi ile başlar, ardından “.” karakterini bulur ve keser.

İşlem sırası, geçerlilik kontrolünü, önceki örnekte olduğu gibi her adımda tam sütunları işlemekten çok daha basit hale getirir. UDF, mantıklı C++ desenleri kullanarak, if-else branşlama ve erken dönüşler ile mantığı basit hale getirmektedir.

JIT Derlemesinin Performans Faydaları

UDF’leri işlemek için JIT dönüşüm yaklaşımını kullanmak, önceden derlenmiş yaklaşımına göre daha hızlı çalışma süreleri elde edilmesini sağlar. Hızlanmanın temel kaynağı, JIT dönüşüm yaklaşımındaki toplam çekirdek sayısının daha düşük olmasıdır. Aynı iş yükü daha az çekirdek ile gerçekleştirilebiliyorsa, işlemler genellikle daha iyi önbellek yerelliği sağlar ve GPU kayıtları, ardından gelen bir çekirdek için global bellekte saklanması gereken ara sonuçları tutabilir.

Şekil 4, üç string dönüşüm örneği için kernel başlatma zaman çizelgesini göstermektedir, burada mavi çubuklar önceden derlenmiş yaklaşımı temsil ederken, yeşil çubuklar JIT dönüşüm yaklaşımını göstermektedir. Zaman çizelgesi verileri, 200M giriş satırı (12.5 GB giriş dosya boyutu) kullanılarak NVIDIA GH200 Grace Hopper Superchip donanımında, CUDA asenkron bellek kaynağı ile toplanmıştır. Not: 10 μs’den daha kısa süreye sahip çekirdekler hariç tutulmuştur.

JIT dönüşüm yaklaşımı, veri boyutu ile ölçeklenebilen bir yarar sağlar. Daha küçük veri boyutlarında, JIT dönüşüm yaklaşımı daha az başlatma yükünden yararlanır ve bu, UDF’nin karmaşıklığına bağlı olarak hızlanma sağlar. Ayrıca daha az yük kullanımı ile JIT dönüşüm yaklaşımı daha az GPU bellek bant genişliği ve işlem kaynakları kullandığı için, daha büyük veri boyutlarında önceden derlenmiş yaklaşıma göre daha fazla hızlanma elde edilir.

Şekil 5, localize_phone örnek durumu için 2x ile 4x arasında ve daha basit extract_email ve format_phone örnek durumları için 1x ile 2x arasında hızlanmaları göstermektedir. Dikkate alınması gereken bir diğer nokta, JIT dönüşüm yaklaşımının, daha az malzeme içeren ara sonuçlar nedeniyle yaklaşık %30 daha büyük veri boyutlarını işleme kapasitesine sahip olmasıdır.

JIT Derlemesinin Özel Maliyetleri

JIT derlemesi de verimli çalışmayı sağlamak için bazı benzersiz zorluklar getirir. JIT dönüşüm yaklaşımı ilk kez çalıştırıldığında, cuDF, LIBCUDF_KERNEL_CACHE_PATH değişkeni ile belirtilen yol üzerindeki bir çekirdek önbelleğini kontrol eder. Bu örnekte önbelleklenmiş çekirdek boyutları yaklaşık 130 KB’dir. Eğer bir önbelleklenmiş çekirdek bulunamazsa, string_transforms örneğinde çekirdek başına yaklaşık 600 ms JIT derleme süresi gerekmektedir. Eğer çekirdek bulunursa, yükleme ise yaklaşık 3 ms sürmektedir.

Bir kez derlenip yüklendikten sonra, aynı işlemdeki sonraki çekirdek çağrılarında ek bir yük bulunmaz. Şekil 6, her tekrarda yeni bir işlemi temsil eden ilk çalışma zamanlamasını göstermektedir ve tekrar 1, boş bir çekirdek önbelleği ile başlar. JIT derlemeli zamanlar, NVRTC ile JIT derlemesinden dolayı ilk yürütmede daha yüksek toplam süre gösterirken, sonraki toplam sürelerin dramatik bir şekilde düştüğü görülmektedir. Toplam süre, örnekte “ısıtma süresi” olarak rapor edilmektedir ve veri boyutu 200M satırdır.

Örneklerde, JIT derlemesi çalışma zamanında ertelenmişse, kırılma veri boyutu yaklaşık 1-3B satır arasında olup, yaklaşık 100M satırda işlem yapılması durumunda geçerlidir. Uygulama katmanı, daha önce derlenmiş çekirdeklerle JIT önbelleğini önceden doldurursa, JIT dönüşümleri genellikle ilk milyon satırdan bile fayda sağlar.

cuDF’de Verimli Dönüşümler ile Başlayın

NVIDIA cuDF, ifadeler ve UDF’ler üzerinde çalışmak için güçlü, esnek ve hızlandırılmış araçlar sunar. CUDA ile hızlandırılmış veri çerçeveleri hakkında daha fazla bilgi için cuDF belgelerine ve rapidsai/cudf GitHub reposuna göz atabilirsiniz. Daha kolay test ve dağıtım için RAPIDS Docker konteynırları ile sürümler ve gece yapılandırmaları da mevcuttur.

libcudf, cuDF’nin C++ alt modülünü kullanarak başlamanız için, rapidsai-nightly Conda kanalıyla önceden derlenmiş ikili dosyaları kurmanızı öneririz. Bu yazıda sergilenen libcudf-example Conda paketini bulup string_transforms örneklerini kurabilirsiniz. Ayrıca libcudf-tests Conda paketi, hem birim testler hem de mikro benchmarklar içermektedir, böylece cuDF önceden derlenmiş ve JIT derlenmiş ifade değerlendiricilerini kolayca çalıştırıp profilleyebilirsiniz.

Kaynak

Nvdia Blog

Exit mobile version