SON DAKİKA

Nvdia

Apache Spark ile GPU Kullanarak Apache Parquet Taramalarını Hızlandırma

Veri boyutları, çeşitli sektörlerdeki işletmelerde büyüdükçe, Apache Parquet, veri depolamanın öne çıkan formatlarından biri haline gelmiştir. Apache Parquet, veriyi sütunlar halinde düzenleyerek yüksek performanslı sorgulama ve analiz yapılmasını sağlamak için tasarlanmış bir sütunlu depolama formatıdır. Parquet bu yapısıyla, bir sorgu için yalnızca gerekli sütunları okuyarak tüm veri satırlarını taramak zorunda kalmadan verimlilik sunar. Verinin verimli yapısı, Parquet’i modern analiz ekosisteminde, özellikle de Apache Spark iş yükleri için popüler bir seçenek haline getirmiştir.

RAPIDS Accelerator for Apache Spark, cuDF üzerine inşa edilmiştir ve veriyi hızlandırılmış bir şekilde okuma ve yazma imkanı sunar. Terabayt boyutundaki büyük veri setlerinde, etkili Parquet taramaları, iyi bir çalışma süresi elde etmek için kritik öneme sahiptir.

Bu yazıda, daha yüksek kayıt kullanımlarından kaynaklanan occupancy sınırlamalarını nasıl azaltabileceğimizi tartışıyor ve benchmark sonuçlarını paylaşıyoruz.

Apache Parquet Veri Formatı

Parquet dosya formatı, verinin sütun gruplarında depolanmasını sağlayan sütun parçalarını kullanır. Meta veri, veriden ayrı olup, gerekli olduğunda sütunların birden fazla dosyaya ayrılmasına olanak tanır (Şekil 1).

A diagram shows a file with a magic number (4 bytes) and then row group, column, page, page header, repetition levels, definition levels, and values for multiple row groups. A breakout section shows the footer, FileMetaData (ThriftCompactProtocol), version, schema, extra key/value pairs, row group metadata, column metadata, footer length, and the magic number again.
Şekil 1. Parquet dosya formatı (kaynak: Dosya Formatı)

Parquet formatı, çok çeşitli veri türleri destekler. Meta veri, bu türlerin nasıl yorumlanacağını belirtir; bu sayede karmaşık mantıksal türleri (örneğin zaman damgaları, dizgeler, ondalık sayılar vb.) temsil edebilir.

Ayrıca meta verileri, daha karmaşık yapılar (örneğin, iç içe türler ve listeler) belirtmek için de kullanabilirsiniz. Veriler, çeşitli kodlama formatlarıyla encode edilebilir; örneğin düz değerler, sözlükler, koşullu uzunluk kodlama, bit paketleme ve daha fazlası.

  - BOOLEAN: 1 bit boolean
  - INT32: 32 bit signed ints
  - INT64: 64 bit signed ints
  - INT96: 96 bit signed ints
  - FLOAT: IEEE 32-bit floating point values
  - DOUBLE: IEEE 64-bit floating point values
  - BYTE_ARRAY: arbitrarily long byte arrays
  - FIXED_LEN_BYTE_ARRAY: fixed length byte arrays

Parquet’de GPU için Occupancy Sınırlamaları

RAPIDS Accelerator for Apache Spark’dan önce, önceki Parquet taramaları uygulaması, tüm Parquet sütun türlerini tek bir işlem kodu setinde destekleyen monolitik bir cuDF çekirdeğiydi.

Spark’ın GPU üzerinde kullanımı arttıkça, Parquet taramalarının performans özelliklerini anlamaya yönelik daha fazla zaman harcandı, çünkü bu, performans açısından kritik bir bileşendi. Bir çekirdeğin ne kadar verimli çalışacağı üzerine etki eden genel kaynaklar şunlardır:

  • Streaming microprocessors (SM’ler): GPU’nun ana işlem birimi, hesaplama görevlerini yürütmekten sorumludur.
  • Paylaşılan bellek: Thread-blok başına tahsis edilen GPU üzerindeki on-chip bellek, bu nedenle aynı bloktaki tüm thread’ler aynı paylaşılan belleğe erişebilir.
  • Registers: Her bir thread tarafından kullanılan ve SM’ler tarafından gerçekleştirilen hesaplama işlemleri için hızlı on-chip GPU belleği.

Parquet taramalarını incelerken, genel GPU occupancy’nin hedeflenen seviyeden daha düşük olduğunu gözlemledik; bunun nedeni ise kayıt limitleriydi. Kayıt kullanımı, CUDA derleyicisinin çekirdek mantığı ve veri yönetimi temelinde oluşturduğu koda bağlıdır.

Parquet’in monolitik çekirdeğinde, tüm sütun türlerini desteklemek için gereken karmaşıklık, yüksek paylaşılan bellek ve kayıt kullanımına neden olan büyük ve karmaşık bir çekirdek oluşturarak, daha fazla optimizasyonun mümkün olmasını kısıtladı ve ölçeklendirmede performans kısıtlamalarına yol açtı.

A diagram shows the loop phases of level stream decoding based on type (flat, nested, or lists); dictionary index decoding or Boolean decoding if applicable; and data copying based on type (fixed width or strings).
Şekil 2. Parquet monolitik çekirdek yapısı

Şekil 2, GPU üzerindeki Parquet veri işleme döngüsünü temsil eder. Her bir blok, büyük ve karmaşık bir çekirdek kodunu taşırken, kendi paylaşılan bellek gereksinimlerini de beraberinde getirir. Çoğu blok tür bağımlıdır ve bu da seçilen işlem sürecinde farklı iş parçacıklarının bağımlı hale gelmesine neden olur. Bu, GPU üzerinde işlerin tamamlanmasını verimsiz hale getirir.

Bir diğer sınırlama ise Parquet bloklarının savaşlar içinde nasıl çözüldüğüydü. Savaşların, daha önce sıralanmış savaşların tamamlanmasını beklemesi gerekiyordu. Bu, farklı parçaların birbirleri ile bağımlı hale gelmesine neden oldu.

Daha isabetli bir performans için blok genişliğinde çözme algoritmasına geçmek kritikidi ancak bu, kayıt sayısını artırıp occupancy’yi daha da kısıtlayabilirdi.

cuDF’de Parquet Mikro çekirdekleri

Yüksek kayıt kullanımlarından kaynaklanan occupancy sınırlamalarını gidermek için, öncelikle Parquet’teki liste türü verileri ön işlemek için daha küçük bir çekirdek geliştirmeyi denedik. Monolitik çekirdekten bir parçayı standalone bir çekirdek haline ayırdığımızda, sonuçlar etkileyici oldu. Genel benchmark sonuçları daha hızlı çalışma süreleri gösterirken, GPU izlemeleri ise daha iyi bir occupancy sağladı.

Bu başarıyla birlikte, farklı sütun türleri için aynı yaklaşımı denedik. Çeşitli türler için mikro çekirdekler, yetenekleri yeniden kullanmak için C++ şablonları kullandı. Bu durum, tür başına kod bakımını ve hata ayıklamayı kolaylaştırdı.

A diagram lists the previous processing phases without the loop or forked paths: level stream decoding for nulls or lists; level stream processing for flat types, nested types, and then lists; dictionary index decoding; Boolean decoding; data copying for fixed width; and data copying for strings.
Şekil 3. Parquet mikro çekirdek yaklaşımı

Parquet mikro çekirdek yaklaşımı, belirli bir tür için gerekli kod yollarını yalnızca geçmek amacıyla derleme zamanı optimizasyonlarından faydalanır. Tek bir monolitik çekirdek yerine, yalnızca o yolu işlemek için gerekli olan kodu içeren birçok bireysel mikro çekirdek oluşturulabilir.

Bu işlem, if constexpr kullanılarak derleme zamanında yapılabilir, böylece kod normal bir şekilde okunabilir, ancak bir kombinasyonun asla alınmayacak kod yollarını içermez (dizgiler veya sabit genişlik, listeler veya hiç liste vb.).

Sabit genişlik türündeki sütunları işlemek için, yalnızca veri kopyalama işleminin gerektiği yeni mikro çekirdek yaklaşımını gösteren basit bir örnek burada sunulmuştur. Bu yöntemde, çoğu işlem özelleştirilmediği için atlanır.

The Figure 2 loop diagram has all phases crossed out except for data copying (fixed width).
Şekil 4. Parquet mikro çekirdek yaklaşımı için sabit genişlik işlemi

WARP’ler arasındaki darboğazları gidermek için yeni mikro çekirdekler, her adımda tüm blokların işlenmesini sağladı, böylece WARP’ler bağımsız olarak verileri daha verimli bir şekilde işlemeye başladı. Bu özellikle dizgiler için önemliydi, çünkü mevcut uygulama yalnızca bir savaş kullanarak dizgileri kopyalamıştır; oysa yeni yöntem 128 thread’lik bir blok kullanarak dizgileri kopyalayabilmektedir.

500-KB parçalar halinde okuma yaparak, NVIDIA RTX A5000 GPU 24GB ile yerel benchmark testleri gerçekleştirdik. Test verilerinde çeşitli değişkenler bulunmaktaydı:

  • Kardinalite 0 ve 1000
  • Koşu uzunluğu 1 ve 32
  • %1 null değerler
  • Veri tekrar ettiğinde uyarlanabilir sözlük kullanımı

Şekil 5, yeni mikro çekirdek yaklaşımı ile GPU üzerindeki Parquet sütun türleri arasındaki throughput iyileştirmelerini göstermektedir.

A bar chart shows the throughput improvements across types: flat integer + float, flat bool, nested columns, list columns, and strings with dictionary.
Şekil 5. Mikro çekirdek yaklaşımı ile throughput iyileşmeleri

Ayrıca, liste kolonlarının parçalara bölünerek okuma işlemini optimize etme girişimi %117 daha yüksek throughput sağlamıştır.

GPU’larda Apache Spark ile Başlamak

Parquet, geniş veri işlemede yaygın olarak kullanılan önemli bir veri formatıdır. GPU, cuDF‘de optimize edilmiş mikro çekirdekler kullanarak Apache Spark’ta Parquet verilerine hız kazandırmaktadır.

İşletmeler, RAPIDS Accelerator for Apache Spark‘ı kullanarak Apache Spark iş yüklerini NVIDIA GPU’lara kolayca geçirebilir. RAPIDS Accelerator for Apache Spark, RAPIDS cuDF kütüphanesinin gücünü ve Spark’ın dağıtık bilgi işlem çerçevesinin ölçeğini birleştirerek GPU’ları kullanarak işleme hızlandırmayı sağlıyor. Mevcut Apache Spark uygulamalarını, kod değişiklikleri yapmadan sadece RAPIDS Accelerator için Spark’ı başlatarak GPU’larda çalıştırabilirsiniz.

Parquet tarama işlemi ve RAPIDS Accelerator for Apache Spark ile pratik yapmak için Spark RAPIDS Parquet hızlandırma Colab defterini kullanabilirsiniz.

Kaynak

Nvdia Blog

Düşüncenizi Paylaşın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

İlgili Teknoloji Haberleri