Apache Spark ile GPU’lar Kullanarak JSON İşlemeyi Hızlandırma

JSON, metin tabanlı veri formatı olarak popülerliğini koruyor ve web uygulamalarıyla veri yönetiminde sistemler arasında karşılıklı etkileşimi sağlıyor. Bu format, 2000’lerin başlarından itibaren web sunucuları ile tarayıcılar arasında iletişim ihtiyacından doğmuştur. Standard JSON formatı, iç içe nesneler de içerebilen anahtar-değer çiftlerinden oluşur. JSON, web işlem bilgilerini depolamada yaygın olarak kullanılmaya başladı ve bazen bir kayıtta 1 GB’den daha büyük değerlere sahip olabilir. Başlangıçta, JSON’un ayrıştırılması ve doğrulanması GPU hızlandırma ile bağlantılı bir görev olarak düşünülmüyordu çünkü metin formatının boyutunda düzensizlikler ve varsayılan bir sıralama yoktu. Ancak, JSON’un birçok kurumsal veri uygulamasındaki rolü arttıkça hızlandırma ihtiyacı da büyümüştür.

Perakendecide GPU Hızlandırma Uygulamaları

Bir Fortune 100 perakende şirketi, JSON formatını temel envanter verilerini saklamak için kullanmaktadır. Bu format, ürün kategorisi ve envanteri ile ilgili yapılandırılmamış verileri içermektedir. Tıklama akış verileri için JSON’un işlenmesi, bir Spark iş yükü altında tek seferde on terabaytın üzerinde JSON verisinin işlenmesini içermektedir.

GPU’lara geçiş yapıldığında, perakendecinin üretim iş yüklerinde belirgin sonuçlar elde edildi. GPU çalışma süresi 16.7 saatten 3.8 saate düşerek yaklaşık 4 kat hız artışı ve benzer bir CPU kümesine kıyasla %80 maliyet tasarrufu sağlandı. Kümedeki düğümler, her düğümde tek bir NVIDIA T4 GPU ile birlikte GCP n1-standard-16 örnekleridir.

GPU acceleration of JSON string processing comparing CPU to GPU showed over 4x improvement on a retailer workload. This production measurement is performed using GCP n1-standard-16 instances with a single T4 attached to each node.
Şekil 1. Perakende iş yükü için GPU hızlandırması“Bu üretim ölçümü, her düğümde tek bir NVIDIA T4 GPU ile GCP n1-standard-16 örnekleri kullanılarak gerçekleştirilmiştir.”

Spark get_json_object Fonksiyonu

JSON için GPU işleme, 22.02 sürümünden itibaren Apache Spark için RAPIDS Hızlandırıcısı’nda bulunmaktadır. Ancak hızlandırılmış işleme ile ilgili bazı zorluklar hâlâ mevcuttur. Perakendeci ile yapılan çalışmalar, Spark’ın get_json_object fonksiyonu kullanılarak JSON kayıtlarını SQL sorgusu içinde anlık olarak ayrıştırmayı gerektiren belirli JSON kayıt işleme ihtiyaçları ortaya çıkarmıştır. JSON formatı, dizi gibi hiyerarşik nesneleri gömme imkânı sunar:

Şekil 2. JSON nesne ve dizi formatı (Kaynak: https://www.json.org/json-en.html)

get_json_object fonksiyonunun amacı, sağlanan yola dayalı olarak JSON kayıt dizgisi içinden bir nesneyi çıkarmaktır. İşte get_json_object fonksiyonunun iç içe geçmiş öğeleri çıkarmak için kullanıldığı basit bir SQL sorgusu örneği:

SELECT get_json_object('[{"a":"b1"}, {"a":"b2"}]', '$[*].a')
["b1","b2"]

Gerçek dünya kullanım durumlarında bu fonksiyon, bir ETL hattında ek işlem için ilgili belirli bir JSON kaydında iç içe geçmiş nesneleri seçmek için kullanılacaktır.

Büyük JSON Dizgilerinin Zorluğu

Perakendecinin iş yükünde, orta genişlikte bir çıktı tablosu ile tek bir SQL sorgu ifadesinin get_json_object fonksiyonunun 50’ye kadar çağrılmasını gerektirebileceği gözlemlenmiştir. Dizgilerin kendisi uzun, ortalama olarak birden fazla KiB boyutundadır. Çağrılardaki sıklığı ve uzun JSON dizgilerini eklediğinizde, işleme sırasında GPU’da önemli bir bellek baskısı ortaya çıkabilir. Bu özellikle GPU’ların L1 belleği için geçerlidir. Başlangıçta GPU üzerindeki uygulama, her kayıdı işlemek için işleme paralelleştirecek şekilde tasarlanmıştı, ancak bu da L1 belleğinin birden fazla kaydı tutmaya çalışması nedeniyle bellek baskısını artırıyordu.

Şekil 3. JSON yol sorgusu için tek çekirdek

Ayrıca, bir iş bloktaki ipliklerin ayrışması durumunda, işleme süresi yavaşlamaktadır çünkü bir ayrışan ipliğin işlemesi gerektiğinde, iş bloğu diğer iplikleri durdurur. CPU kümesinde yapılan 30 TB’lık bir iş yükü için orijinal sonuç 16 saatken, karşılaştırılabilir bir GPU kümesinde 16.7 saat almıştır.

Perakendecinin sorgusu ve veri setine derinlemesine bakıldığında, verilerin JSON nesneleri içinde seyrek alanlar içerdiği gözlemlenmiştir. Bu, belirli bir kayıtta bir alanın görünebilme olasılığının çok düşük olduğu anlamına gelmektedir; özellikle, alanların %85’inin %0.01’den az kayıtta göründüğü bilinmektedir. Bu nedenle, ipliklerin işleme gelirken erken ayrışması olasılığı yüksektir. İdeal senaryo, aynı gruptaki ipliklerin benzer veriler üzerinde çalışmasıdır.

CUDA programlama rehberine göre:

“Bir grup, aynı anda tek bir ortak talimat uygular; bu nedenle, bir grubun tüm iplikleri, yürütme yolunda hemfikir olduğunda tam verimlilik elde edilir. İpliklerin bir grubun ayrışması durumunda, grup, her bir dal yolunu yürütür ve o yolda olmayan iplikleri devre dışı bırakır.”

Perakendeci sorgularındaki sık get_json_object çağrılarının GPU üzerindeki ilk yavaşlığı, iplik ayrışması nedeniyle doğrulandığı için bu tür işlemleri optimize etme çalışmaları başlamıştır.

GPU’da JSON İşlemeyi Geliştirme

Özellikle büyük dizgilerle seyrek verilerle JSON işlemesinin optimize edilmesi için, gruplardaki veri işleme yönteminin iyileştirilmesi gerekmekteydi. Performans artırmak amacıyla, perakendecinin iş yükü için hızlandırılmış bir iş yüküne yardımcı olmak üzere ardışık optimizasyonlar gerçekleştirdik.

Optimizasyon çabalarını doğrulamak için tek düğümlü ölçümler gerçekleştirerek etkilerini göstermeyi hedefledik. Yerel ölçüm ortamı, 32 çekirdekli AMD Ryzen Threadripper PRO 5975WX (CPU) ve NVIDIA RTX A6000 48GB (GPU) içermektedir. Ölçüm verileri, perakendecinin JSON verilerine benzeyen yaklaşık 9.2 GB’lık (açık) ve 6.4 GB’lık (snappy sıkıştırma ile saklanmış) oluşturulmuş JSON verisi içerir.

Yerli ölçümlerde, büyük dizgili oluşturulmuş JSON verileri ile, başlangıçta CPU işlemesinden sadece biraz hızlı olan GPU işleme, optimizasyonlar sonrasında 5 kat hız kazandı.

Şekil 4. Tek çekirdek veri iplik bloğuna göre

Uygulanan ilk teknik, aynı gruptaki veriler için birden fazla sorgunun birleştirilmesi oldu. Eğer büyük bir kaydın farklı alanlarında sorgu yapılırken ipliklerin aynı grupta toplanmasını sağlarsak, iplik ayrışmasını dengeleyebilir ve bellek baskısını azaltabiliriz. Bu, yerel ölçümlerimizde 3.2 katlık bir iyileşmeyi beraberinde getirdi.

Şekil 5. Tek çekirdek sıralı veri iplik bloğuna göre

Bununla birlikte, aynı JSON yolundaki sonraki sorgular arasında hâlâ iplik ayrışması gerçekleşebildiğini fark ettik. Bu nedenle, sorguları leksikografik olarak sıraladık. Bu, aynı grubun içerisinde benzer işleme yapmak için ipliklerin ayrışma olasılığını artırarak daha fazla iyileşme sağladı. Bu optimizasyon uygulandıktan sonra, yerel ölçümlerimizde %10 daha fazla iyileşme sağlanarak toplamda 3.6 kat hız artışı elde edildi.

Son olarak, JSON nesnelerini işlerken tek karakterli ayrıştırmadan uzaklaşıp daha çok veri paralel tokenizer kullanma yolunda ilerliyoruz. Bu optimizasyon, %50 daha fazla iyileşme göstermekte ve toplamda 5.6 kat hız artışına yol açmaktadır. Uygulamanın bu yıl piyasaya sürülmesi beklenmektedir.

Şekil 6. GPU ile JSON dize işlemede hızlandırma

Önemli Noktalar

Büyük miktarda dizgi verilerinin işlenmesi, GPU için zorluklar doğuruyor; bu nedenle, özel optimizasyonlar gereklidir. Apache Spark için RAPIDS Hızlandırıcısı ve cuDF, GPU’larda hız artışı sağlayacak şekilde JSON işlemesini geliştiriyor.

GPU’larda Apache Spark ile Başlamak

Kurumsal şirketler, RAPIDS Hızlandırıcısı ile mevcut Spark iş yüklerini NVIDIA GPU’lara geçiş yapmak için sıfır kod değişikliği ile faydalanabilir. RAPIDS Hızlandırıcısı, GPU’ların gücünü kullanarak işlemi hızlandırmakta ve Spark dağıtılmış bilişim çerçevesinin ölçeği ile birleştirmektedir.

JSON işlemesi ve RAPIDS Hızlandırıcısı için Colab not defteri ile pratik yapın ve daha fazlasını öğrenmek için GTC 2025 oturumuna göz atın.

Gelecek Çalışmalar

GPU’larda dizgi işleme için ek optimizasyonlar planlanmakta ve JSON’u hızlandırmada kullanılan tekniklerin benzerleri daha fazla ifade ve işlevsellik için kullanılacaktır.

Gelişmeleri takip etmek veya katkıda bulunmak için açık kaynak projelerine göz atın: RAPIDS Hızlandırıcısı ve cuDF.

Kaynak

Nvdia Blog

Exit mobile version