3.8K Views
March 16, 24
スライド概要
2024-03-15セミナー資料
かぴばら
PG-Strom v5.0 ~変わったこと、できること~ ヘテロDB株式会社 チーフアーキテクト 兼 CEO 海外 浩平 <[email protected]>
HeteroDB社について ヘテロジニアスコンピューティング技術を データベース領域に適用し、 誰もが使いやすく、安価で高速なデータ分析基盤を提供する。 会社概要 商号 創業 拠点 事業内容 ヘテロDB株式会社 2017年7月4日 東京都品川区 高速データベース製品の販売 GPU&DB領域の技術コンサルティング 代表者プロフィール 海外 浩平|KaiGai Kohei OSS開発者コミュニティにおいて、PostgreSQLやLinux kernelコア機能の 開発に15年以上従事。主にセキュリティやFDWなどの機能強化に貢献 し、PostgreSQLのMajor Contributorとしても知られる。 IPA未踏ソフト事業において“天才プログラマー”認定 (2006) GPU Technology Conference Japan 2017でInception Awardを受賞 2 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
製品概要 PG-Stromとは? PG-Strom: GPUとNVMEの能力を最大限に引き出し、 TB級のデータを高速処理するPostgreSQL向け拡張モジュール off-loading App GPU ➢ GpuScan / GpuJoin / GpuPreAgg ➢ GPU-Direct SQL ➢ Apache Arrow support (with min/max statistics support) ➢ GPU Memory Cache ➢ Asymmetric Partition-wise JOIN/GROUP BY ➢ BRIN-Index support ➢ PostGIS support (with GiST-index on GpuJoin) ➢ HyperLogLog Cardinarity ➢ pg2Arrow / mysql2arrow / pcap2arrow 【機能】 集計/解析ワークロードの透過的なGPU高速化 SQLからGPUプログラムを自動生成し並列実行 GPU-Direct SQLによるPCIeバスレベルのI/O最適化を行う Apache Arrowに対応し、IoT/M2Mログデータの処理にフォーカス PostGIS関数・演算子のサポートで、位置情報分析を高速化 3 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPUの発展と共に、 PG-Stromの進化を振り返る 4 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPUとはどんなプロセッサか?(1/3) 多数のコアと広帯域メモリによる強力な並列演算性能を有する。 CPU Cache CUDA Core CUDA Core CUDA Core CUDA Core CUDA Core CUDA Core CUDA Core CUDA Core 広帯域メモリ 5 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPUとはどんなプロセッサか?(2/3) スレッド同士での同期やデータ交換を低コストで実行できる step.1 item[0] item[1] item[2] item[3] item[4] GPUを用いた item[5] Σi=0...N-1item[i] item[6] item[7] 配列総和の計算 item[8] item[9] item[10] item[11] SELECT count(X), sum(Y), avg(Z) FROM my_table; item[12] item[13] item[14] item[15] ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● ● step.2 ◆ step.4 step.3 ▲ ■ ◆ ◆ ▲ ◆ ◆ ▲ ◆ ◆ ▲ ■ log2N ステップで items[]の総和を計算 ◆ 集約関数の計算で用いる仕組み HW支援によるコア間の同期機構 6 ★ 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPUとはどんなプロセッサか?(3/3) ▌非常に多数の演算コアを連動して並列処理を行う NVIDIA H100の場合、144SMを搭載 ➔ 144 x 64 = 9,216 INTコア ▌ハードウェアのタスクスイッチ&同期機構を用いたアルゴリズムが前提 基本、ループ処理はマルチスレッドに。 CPUにおけるHyper-Threadingのお化けのようなモノ。 NVIDIA H100 のブロックダイアグラム 7 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PostgreSQLにGPUを試そうとしたきっかけ May-2011 ▌PGconf 2011 (Ottawa) で聴講したあるセッション・・・ Parallel Image Searching Using PostgreSQL and PgOpenCL Running PostgreSQL Stored Procedures on a GPU ✓ https://www.pgcon.org/2011/schedule/events/352.en.html 画像処理用のストアドプロシジャを、GPU用のプログラミング環境 OpenCL で作成するための拡張モジュールについて。 A列 B列 C列 D列 幅の小さいデータでも、 大量の行を並べれば 長大なBLOBと同じく GPU並列処理が効くのでは? 8 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』 E列
実際に作ってみた(1/2) Jan-2012 FDWを使用して、テーブル構造の裏側に 簡易的な列ストアを作成した。 ※ 当時はFDWが唯一のエグゼキュータを 拡張するための方法。 CPUでテーブルをスキャンし、同時に、 並行してGPUで条件句を処理するという 構造を持っていた。 ※ 当時は並列クエリ実行が無かった 9 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
実際に作ってみた(2/2) WHERE条件句から CUDA C のコードを 自動生成してJITコンパイルを行う。 ※ EXPLAINすると CUDA C の生のソース コードが表示される。かなりシュール。 10 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』 Jan-2012
PostgreSQL v9.5における機能強化 May-2015 CustomScan API SQL PostgreSQL本体へのパッチを必要せず、純粋に 拡張モジュールのみでGPU実行を実装できるように。 Parser パース木 Optimizer CustomScan API add_scan_path add_join_path Executor 実行計画 execBegin BeginCustomScan Exec ExecCustomScan execEnd EndCustomScan 実行結果 11 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』 拡張モジュールによる実装
GPU-Direct SQLの着想と開発(1/3) 2015 (当時の)PG-Stromを含む、 GPU-DBはデータがオンメモリ前提 GPUコア ストレージに落ちたら「負け」 720GB/s GPU Device Memory 一方この頃、NVME-SSD製品が登場 安価な高速SSDがブレイクの兆し。 16GB/s CPU CPU Host Memory 一台あたり 60GB/s 0.5GB/s ストレージ (HDD/SSD) 12 3GB/s NVME-SSD 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPU-Direct SQLの着想と開発(2/3) 2015 NVIDIA GPUDirect RDMA 物理アドレス空間 ホストメモリ nvme.ko ドライバ NVME-READ From: Block 1234 Qty: 32 Dest: 0x34567000 NVME コマンド 13 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』 デバイスメモリ nvme_strom.ko ドライバ NVME-READ From: Block 2345 Qty: 32 Dest: 0x45678000 NVME コマンド
GPU-Direct SQLの着想と開発(3/3) 2016 実験用に購入した Intel SSD 750 (400GB) の 理論帯域まで出ている (!) ✓ GPU-Direct SQL(当時は SSD-to-GPU Direct SQL)により、メモリサイズを越えた 大量データ(数TB~)を処理する事が可能に。 ➔ この特徴が、PG-Stromが他のGPU-DB製品と比べ、異質な進化をするきっかけに。 ✓ この頃は、猫も杓子も “Deep Learning!” “Deep Learning!” 14 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PG-Stromの主要機能と、 v3.x のアーキテクチャ 15 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能① GPUコードの自動生成(1/2) PostgreSQL SQLパーサ ユーザやアプリからは、 PostgreSQLサーバに対し 全く同一のSQLを投げて いるように見える。 WHERE句や JOIN...ONなど要素に 分解し、GPUでの 実行可否を問う PostgreSQL オプティマイザ PostgreSQL エグゼキュータ GPUコード ジェネレータ GPU版 SCAN/JOIN/GROUP BY 実行時コンパイラ 動的生成 GPUコード (NVRTC) PG-Strom 拡張モジュール GPU 実行形式 バイナリ 静的ビルド GPUライブラリ WHERE句など相当の、 GPU向けコードを生成 SQLから自動的にGPUコードを生成し、WHERE句やJOIN...ONに相当 する処理を、GPUの持つ数千コアで並列実行する事ができる。 処理の大部分は 静的にビルドされ、 コンパイル時間を短縮 ➔ PostgreSQL向けアプリケーションを“そのまま”使い続ける事ができる。 ✓ 一方で、実行時コンパイルに200ms~以上の時間を要していた。 16 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能①
GPUコードの自動生成(2/2)
postgres=# EXPLAIN VERBOSE
SELECT lo_orderkey, lo_shippriority FROM lineorder
WHERE lo_orderdate = 19960313 AND lo_shipmode = 'AIR';
QUERY PLAN
------------------------------------------------------------------------------------------------------------Gather (cost=21819.73..50250260.15 rows=345152 width=10)
Output: lo_orderkey, lo_shippriority
Workers Planned: 2
-> Parallel Custom Scan (GpuScan) on public.lineorder (cost=20819.73..50214744.95 rows=143813 width=10)
Output: lo_orderkey, lo_shippriority
GPU Projection: lineorder.lo_orderkey, lineorder.lo_shippriority
GPU Filter: ((lineorder.lo_orderdate = 19960313) AND (lineorder.lo_shipmode = 'AIR'::bpchar))
GPU Preference: GPU0 (NVIDIA A100-PCIE-40GB)
GPUDirect SQL: enabled
Kernel Source: /var/lib/pgdata/pgsql_tmp/pgsql_tmp_strom_559195.2.gpu
Kernel Binary: /var/lib/pgdata/pgsql_tmp/pgsql_tmp_strom_559195.3.ptx
(11 rows)
DEVICE_INLINE(pg_bool_t)
__exprBoolOp_1(kern_context *kcxt, pg_int4_t &KVAR_6, pg_bpchar_t &KVAR_17)
{
pg_bool_t status __attribute__((unused));
lo_orderdate = 19960313
cl_bool
has_null = false;
に相当
status = pgfn_int4eq(kcxt, KVAR_6, pg_int4_param(kcxt,0));
if (PG_BOOL_ISFALSE(status))
return status;
has_null |= status.isnull;
status = pgfn_bpchareq(kcxt, KVAR_17, pg_bpchar_param(kcxt,1));
lo_shipmode = ‘AIR’
if (PG_BOOL_ISFALSE(status))
return status;
に相当
status.isnull |= has_null;
return status;
}
/var/lib/pgdata/pgsql_tmp/pgsql_tmp_strom_559195.2.gpu
17
2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能② GPU-Direct SQL(1/3) 「ゴミデータ」かどうか、CPU/RAMにロードするまで分からない。 PCI-E Bus Storage Block Read 大量の ”ゴミデータ” も含む Buffer Copy SCAN JOIN Buffer Copy 18 GROUP BY 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能② GPU-Direct SQL(2/3) P2P-DMAを利用し、NVME-SSDとGPUを直結してデータ転送 Storage Block Read by NVIDIA GPUDirect Storage SCAN P2P-DMA JOIN GROUP BY P2P-DMA : Peer-to-Peer Direct Memory Access PCI-E Bus 不要データを除去済み データ量:小 特許 2017-545609 データベース処理高速化のシステム、方法、及び、プログラム 特許 2019-540125 データベース・クエリ効率化のためのシステム、方法、および、プログラム 19 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能② GPU-Direct SQL(3/3) Star Schema Benchmark (SF=999; 875GB) Query Execution Throughput [MB/s] CPU: AMD EPYC 7402P (24C; 2.8GHz), GPU: NVIDIA A100 [PCI-E; 40GB], SSD: Intel D7-5510 (U.2; 3.84TB) x4 20,000 18,915 18,902 19,164 18,351 19,158 17,278 17,220 15,995 16,068 16,410 16,020 15,978 15,000 10,000 5,000 2,648 2,690 2,687 2,500 2,491 2,480 2,633 2,128 2,572 2,531 2,124 2,079 2,152 0 Q1_1 Q1_2 Q1_3 Q2_1 Q2_2 Q2_3 PostgreSQL v13.4 Total Storage Read Throughput [MB/s] 18,317 Query Execution with GPU-Direct SQL 20,000 Q3_1 Q3_2 Q3_3 Q3_4 Q4_1 Q4_2 Q4_3 PG-Strom v3.3devel [Heap] H/W処理能力に近いパフォーマンスで データを読み出し、クエリを処理している。 nvme3 15,000 単位時間あたりの処理能力が低いため、 結果、クエリの応答時間が伸びてしまう。 nvme2 10,000 nvme1 Query Execution with Filesystem on PostgreSQL Heap Tables 5,000 nvme0 0 0 20 40 60 80 100 120 140 160 180 200 220 240 260 Elapsed Time [sec] 20 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』 280 300 320 340 360 380 400
主要機能③ Apache Arrow対応(1/3) ▌Arrow形式の特徴 列指向で分析用途向けに設計されたデータ形式 アプリケーションによらず、共通のデータ交換形式として利用可能 整数、実数、日付時刻、文字列など基本的なデータ型を定義 更新・削除は無理だが、追記に強い(➔ ログデータに向いた形式) PostgreSQL / PG-Strom NVIDIA GPU 21 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能③ Apache Arrow対応(2/3) SSD-to-GPU Direct SQL機構を使って、被参照列だけを転送する。 NVMe SSD GPU クエリの被参照列のみ、 ダイレクトデータ転送 WHERE-clause JOIN GROUP BY PCIe Bus Apache Arrow形式を解釈し、 データを取り出せるよう GPUコード側での対応。 SSD-to-GPU P2P DMA Results 小規模の処理結果だけを PostgreSQLデータ形式で返す metadata ▌なぜApache Arrow形式がログデータ処理に適しているのか? 被参照列のみ読み出すため、I/O量が少なくて済む GPUメモリバスの特性から、プロセッサ実行効率が高い Read-onlyデータなので、実行時のMVCC検査を行う必要がない 22 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能③ Apache Arrow対応(3/3) Pg2Arrow により、SQL実行結果をArrow形式で書き出す事ができる。 ✓ 基本的な使い方は、-cで指定したSQLの実行結果を、 -oで指定したファイルに書き出す。 $./pg2arrow -h Usage: pg2arrow [OPTION]... [DBNAME [USERNAME]] General options: -d, --dbname=DBNAME database name to connect to -c, --command=COMMAND SQL command to run -f, --file=FILENAME SQL command from file -o, --output=FILENAME result file in Apache Arrow format Arrow_Fdw Pg2Arrow Apache Arrow Data Files 23 Arrow format options: -s, --segment-size=SIZE size of record batch for each (default is 256MB) Connection options: -h, --host=HOSTNAME -p, --port=PORT -U, --username=USERNAME -w, --no-password -W, --password database server host database server port database user name never prompt for password force password prompt Debug options: --dump=FILENAME --progress dump information of arrow file shows progress of the job. 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能④ GPU-Cache(1/2) PostgreSQLのストレージ層をAs-Isで使用するケース ▌PostgreSQLストレージ Parallel Scan/Join/GroupBy source buffer PostgreSQLのストレージAPIを用いて、 ファイル or バッファから読み出した データをGPUに転送して処理。 問題点:基本的に遅い。 destination buffer 非同期DMA source buffer destination buffer next step shared buffer filesystem PostgreSQL tables 24 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能④ GPU-Cache(1/2) GPU-Direct SQLを用いるケース ▌PostgreSQLストレージ Parallel Scan/Join/GroupBy source buffer PostgreSQLのストレージAPIを用いて、 ファイル or バッファから読み出した データをGPUに転送して処理。 問題点:基本的に遅い。 destination buffer ▌GPU-DirectSQL P2P DMA memcpy (NVME/NVME-oF ➔ GPU) NVME-SSDからGPUへP2P-RDMAを用いた destination buffer next step 直接のデータ転送。GPUでクエリ処理。 問題点:大容量データ(100GB~)で ないと効果を実感しにくく、 適用範囲が限定的。 shared buffer filesystem PostgreSQL tables 25 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能④ GPU-Cache(1/2) GpuCacheでDBテーブルの内容をGPUに常駐させておく ▌PostgreSQLストレージ Parallel Scan/Join/GroupBy GPU Cache PostgreSQLのストレージAPIを用いて、 ファイル or バッファから読み出した データをGPUに転送して処理。 問題点:基本的に遅い。 destination buffer ▌GPU-DirectSQL Asynchronous Log Applying NVME-SSDからGPUへP2P-RDMAを用いた REDO Log buffer destination buffer next step high-frequency, small-volume shared buffer PostgreSQL tables 26 transactional workloads 直接のデータ転送。GPUでクエリ処理。 問題点:大容量データ(100GB~)で ないと効果を実感しにくく、 適用範囲が限定的。 ▌GPU-Cache GPU上に確保したキャッシュ領域に、 テーブルの内容を予めロードする。 AFTERトリガを用いた差分更新が可能。 問題点:最速ではあるが、データ容量に 限りがある。(~数十GB) 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
Used as a circular buffer 主要機能④ GPU-Cache(2/2) last position where log entries are already applied to AFTER ROW TRIGGER INSERT PostgreSQL Backend UPDATE PostgreSQL Backend DELETE PostgreSQL Backend REDO Log Entry REDO Log Entry REDO Log Entry REDO Log Entry current position to write log entries REDO Log Buffer (host shared memory) UPDATE PostgreSQL Backend Cached Table トランザクション毎にGPUメモリを更新すると遅延が大きいため、トリガを使って、 更新履歴をメモリ上のREDO Log Bufferに格納する。 27 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能④ GPU-Cache(2/2) GPU Device Memory GPU Cache readPosold Load the multiple log entries at once, then GPU kernel updates the GPU cache in parallel, by thousands processor cores. REDO Log Entry REDO Log Entry REDO Log Entry writePosold readPosnew REDO Log Entry Background worker (GPU Service) REDO Log Entry REDO Log Entry writePosnew REDO Log Buffer (host shared memory) Cached Table トランザクション毎にGPUメモリを更新すると遅延が大きいため、トリガを使って、 更新履歴をメモリ上のREDO Log Bufferに格納する。 REDO Log Entryが一定量溜まると、GPU ServiceがこれをGPUに転送し、GPU Cacheを更新する。 28 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
主要機能④ GPU-Cache(2/2) GPU Device Memory ② launch GPU kernels for Scan/Join/GroupBy PostgreSQL Backend (analytic) GPU kernels for SQL GPU Cache Load the log entries not applied yet, at the time when OLAP workloads begins SQL execution. ① command to apply redo log entries, if any Background worker (GPU Service) readPos REDO Log Entry REDO Log Entry writePos REDO Log Buffer (host shared memory) Cached Table トランザクション毎にGPUメモリを更新すると遅延が大きいため、トリガを使って、 更新履歴をメモリ上のREDO Log Bufferに格納する。 REDO Log Entryが一定量溜まると、GPU ServiceがこれをGPUに転送し、GPU Cacheを更新する。 GpuJoinなど分析系処理の実行時には、先ず未反映のREDO Logを適用してから、SQL処理を 行うGPU Kernelを起動する(※ストレージの読出しは発生しない) 29 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PG-Strom v3.x の課題(1/2) fork(2) PostgreSQL Backend Postmaster Process DBクライアント PG-Strom GPU PostgreSQLはマルチプロセスモデル → クライアント毎にfork(2)してバックエンドを生成 30 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PG-Strom v3.x の課題(1/2) fork(2) PostgreSQL Backend Postmaster Process PG-Strom CUDA Context working memory DBクライアント GPU PostgreSQLはマルチプロセスモデル → クライアント毎にfork(2)してバックエンドを生成 PG-Stromを使用するバックエンドプロセスは、APIの使用時に必ずCUDA Contextを生成する。 ✓ CUDA Context = GPU処理にとってのプロセス(リソースやスケジューリングの単位) 31 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PG-Strom v3.x の課題(1/2) fork(2) Postmaster Process DBクライアント PostgreSQL Backend PostgreSQL Backend PostgreSQL Backend PG-Strom PG-Strom PG-Strom CUDA Context CUDA Context CUDA Context working memory working memory working memory GPU PostgreSQLはマルチプロセスモデル → クライアント毎にfork(2)してバックエンドを生成 PG-Stromを使用するバックエンドプロセスは、APIの使用時に必ずCUDA Contextを生成する。 ✓ CUDA Context = GPU処理にとってのプロセス(リソースやスケジューリングの単位) CUDA Contextは存在するだけでリソースを消費する(GPUメモリ数百MB) ➔ 同時接続クライアント数が増えると地獄!! 32 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PG-Strom v3.x の課題(1/2) fork(2) Postmaster Process DBクライアント PostgreSQL Backend PostgreSQL Backend PostgreSQL Backend PostgreSQL Worker PostgreSQL Backend PG-Strom PG-Strom PG-Strom PG-Strom PG-Strom CUDA Context CUDA Context CUDA Context CUDA Context CUDA Context working memory working memory working memory working memory working memory GPU 何もしなくても 消費するリソース PostgreSQLはマルチプロセスモデル → クライアント毎にfork(2)してバックエンドを生成 PG-Stromを使用するバックエンドプロセスは、APIの使用時に必ずCUDA Contextを生成する。 ✓ CUDA Context = GPU処理にとってのプロセス(リソースやスケジューリングの単位) CUDA Contextは存在するだけでリソースを消費する(GPUメモリ数百MB) ➔ 同時接続クライアント数や並列処理ワーカーが増えると地獄!! 33 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PG-Strom v3.xの課題(2/2) ▌SQLの実行に最低限必要な時間 CUDA Contextの生成(初期化) ✓ 100~200ms程度 ✓ パラレルクエリの場合、各ワーカー毎に初期化が必要 GPUコードのビルド(実行時コンパイル) ✓ 200ms~ ※クエリの複雑さによる PG-Strom v3.5 の場合 =# select count(*) from lineorder_8m where lo_orderpriority = '2-HIGH'; count --------1604233 (1 row) Time: 1132.471 ms (00:01.132) 34 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PG-Strom v3.xの課題(2/2) ▌SQLの実行に最低限必要な時間 CUDA Contextの生成(初期化) ✓ 100~200ms程度 ✓ パラレルクエリの場合、各ワーカー毎に初期化が必要 GPUコードのビルド(実行時コンパイル) ✓ 200ms~ ※クエリの複雑さによる PG-Strom v3.5 の場合 =# select count(*) from lineorder_8m where lo_orderpriority = '2-HIGH'; count --------1604233 (1 row) Time: 1132.471 ms (00:01.132) PG-Strom v5.0 の場合 =# select count(*) from lineorder_8m where lo_orderpriority = '2-HIGH'; count --------1604233 (1 row) Time: 114.781 ms 35 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
PG-Strom v5.0で変わったこと 36 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPU-Serviceへの集約(1/2) CUDA Contextの生成ごとに消費されるワーキングメモリの節約 PG-Strom v3.x 系列 PG-Strom v5.0 fork(2) fork(2) Postmaster Process PostgreSQL Backend PostgreSQL Backend PostgreSQL Backend PG-Strom PG-Strom PG-Strom CUDA Context CUDA Context CUDA Context working memory working memory working memory Postmaster Process PostgreSQL Backend PostgreSQL Backend PG-Strom PG-Strom Local connection to GPU Service 37 GPU Service (multithreads) CUDA Context working memory GPU GPU ✓ コード品質やでバック手法に対する知見が十分で なかった時期、デバッグを容易にするメリット。 ✓ メモリコピーのコストをやや過大に見積もり。 Background Worker ✓ CUDA Context初期化時間、およびワーキング メモリ(数百MB~1GB)の節約。 ✓ CUDA Contextスイッチの削減とGPU使用率改善 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPU-Serviceへの集約(2/2) ▌GPU-Serviceの役割 PG-Stromが利用する唯一のCUDA Contextを保持する。 PostgreSQLバックエンドプロセスからのリクエストを受け付け、これを マルチスレッドで並列に処理(pg_strom.max_async_tasks) GPU-Cacheの使用するバッファを管理する。 ▌新設計の利点 CUDA Contextの消費するリソースの節約と、生成/初期化の時間を節約 GPU側のコンテキストスイッチの必要がなくなる GpuJoinのInner-bufferをCUDA Managed Memoryとして割当て可 プロセス間通信のコストは大きくない。 GPU Kernel起動 UNIXドメインソケット GPU GPU Service PostgreSQLバックエンド cuFileRead() 38 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
コード生成:CUDA C++から疑似命令コードへ(1/3)
=# explain verbose select
from
where
and
and
and
sum(lo_extendedprice*lo_discount) as revenue
lineorder,date1
lo_orderdate = d_datekey
d_year = 1993
lo_discount between 1 and 3
lo_quantity < 25;
QUERY PLAN
--------------------------------------------------------------------------------------------Aggregate (cost=3161089.82..3161089.83 rows=1 width=32)
Output: pgstrom.sum_fp_num((pgstrom.psum(((lineorder.lo_extendedprice * lineorder.lo_discount))::double precision)))
-> Custom Scan (GpuPreAgg) on public.lineorder (cost=3161089.81..3161089.82 rows=1 width=32)
Output: (pgstrom.psum(((lineorder.lo_extendedprice * lineorder.lo_discount))::double precision))
GPU Projection: pgstrom.psum(((lineorder.lo_extendedprice * lineorder.lo_discount))::double precision)
GPU Scan Quals: ((lineorder.lo_discount >= '1'::numeric) AND (lineorder.lo_discount <= '3'::numeric) AND
(lineorder.lo_quantity < '25'::numeric)) [rows: 600128800 -> 80699690]
GPU Join Quals [1]: (lineorder.lo_orderdate = date1.d_datekey) ... [nrows: 80699690 -> 11519510]
GPU Outer Hash [1]: lineorder.lo_orderdate
GPU Inner Hash [1]: date1.d_datekey
GPU-Direct SQL: enabled (GPU-0)
:
Scan Quals OpCode: {Bool::AND args=[{Func(bool)::numeric_ge args=[{Var(numeric): slot=0, expr='lo_discount'},
{Const(numeric): value='1'}]}, {Func(bool)::numeric_le args=[{Var(numeric): slot=0, expr='lo_discount'}, {Const(numeric):
value='3'}]}, {Func(bool)::numeric_lt args=[{Var(numeric): slot=1, expr='lo_quantity'}, {Const(numeric): value='25'}]}]}
Join Quals OpCode: {Packed items[1]={JoinQuals: {Func(bool)::int4eq args=[{Var(int4): kvec=0x2a000-2c800,
expr='lo_orderdate'}, {Var(int4): slot=5, expr='d_datekey'}]}}}
Join HashValue OpCode: {Packed items[1]={HashValue arg={Var(int4): kvec=0x2a000-2c800, expr='lo_orderdate'}}}
Partial Aggregation OpCode: {AggFuncs <psum::fp[slot=2, expr='(((lo_extendedprice * lo_discount))::double
precision)']> arg={SaveExpr: <slot=2, type='float8'> arg={Func(float8)::float8 arg={Func(numeric)::numeric_mul
args=[{Var(numeric): kvec=0x1c000-2a000, expr='lo_extendedprice'}, {Var(numeric): kvec=0x0000-e000, expr='lo_discount'}]}}}}
Partial Function BufSz: 16
-> Seq Scan on public.date1 (cost=0.00..78.96 rows=365 width=4)
Output: date1.d_datekey
Filter: (date1.d_year = 1993)
v3.x系列では、自動生成した
(22 rows)
CUDA C++ソースコードの
ファイル名が表示されていた部分
39
2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
コード生成:CUDA C++から疑似命令コードへ(2/3) ▌疑似命令コードの利点 CUDA C++コードと異なり、実行時コンパイルの処理ステップが不要 ➔ 初回実行に200ms~ 程度の時間がかかっていた。 将来的に、NVIDIA GPU以外のデバイスでの処理もスコープに…。 ✓ CSD (Computational Storage Drive) などが候補 ▌処理の高速化のために GPU-Serviceで、GPU Kernel起動前にOpCode ➔ 関数ポインタ変換 struct kern_expression { uint32_t len; /* length of this expression */ TypeOpCode exptype; const xpu_datum_operators *expr_ops; uint32_t expflags; /* mask of KEXP_FLAG__* above */ FuncOpCode opcode; xpu_function_t fn_dptr; uint32_t nr_args; /* number of arguments */ uint32_t args_offset; /* offset to the arguments */ char data[1] __MAXALIGNED__; }; データ型に固有の情報や、 read/writeハンドラへの参照 typedef bool (*xpu_function_t)(kern_context *kcxt, const kern_expression *kexp, xpu_datum_t *__result); 40 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
コード生成:CUDA C++から疑似命令コードへ(3/3) ARM搭載Computational Storage Driveでの実験 PostgreSQL & PG-Strom CSDデバイスの詳細 実行結果 CSD側でScan, Join, (Partial) GroupBy を 実行した結果のみ dpuserv SQL疑似命令列 NFSマウント 製造元: NGD Systems 記憶素子:NAND Flash 8.0TB QLC(詳細不明) インターフェース:U.2 NVME PCI-E 3.0 x4 CPU: Arm Cortex A53 (Quad cores, 1.5GHz) RAM: 8.0GB DDR4 (6.0GB for user programs) OS: Ubuntu 18.04.5 LTS (aarch64) 評価用データベース (ssbm: lineorder [87GB]) テーブルスペース 平均 SeqRead 425MB/s 41 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPUコードの内部データ形式の改善(1/2) GPUの能力をフルに引き出すには、適切なデータ形式の選択が必要 ▌不連続なデータアクセス (random memory access) ✓ v3.xでのPGデータ表現 typedef struct { int4_t value; bool isnull; } pg_int4_t; 256bit幅のメモリトランザクション中、 32bit x 1 = 32bitのみ有効なデータ (バス使用率 12.5%) GPUコア ➔隣接領域へのデータアクセスに なりにいデータ構造。 32bit 32bit 32bit 32bit 32bit 32bit Memory transaction width: 256bit ▌隣接領域に対するデータアクセス (coalesced memory access) ✓ v5.0でのPGデータ表現 #define KVEC_UNITSZ (MAXTHREADS_PER_BLOCK * 2) typedef struct { bool isnull[KVEC_UNITSZ]; int4_t values[KVEC_UNITSZ]; GPUコア } kvec_int4_t; 256bit幅のメモリトランザクション中、 32bit x 8 = 256bitが有効なデータ (バス使用率 100.0%) ➔データアクセスが必ず隣接領域を参照 できるよう、データ構造を変更。 32bit 32bit 32bit 32bit 32bit 32bit 32bit 32bit Memory transaction width: 256bit 42 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
GPUコードの内部データ形式の改善(2/2) 背景はハイエンドGPUの高騰と需給の逼迫 NVIDIA H100 NVIDIA L40S NVIDIA RTX 6000 Ada [80GB, PCI-E] [48GB, PCI-E] [48GB, PCI-E] 約500万円 約180万円 約128万円 (2024年3月時点市場価格) (2024年3月時点市場価格) (2024年3月時点市場価格) GPU世代 Hopper (2022) Ada Lovelace (2022) Ada Lovelace (2022) CUDA Core数 (INT32) 7,296 (114SM) 9,088 (142SM) 9,088 (142SM) CUDA Core Clock 1065MHz / 1620MHz 1065MHz / 2520MHz 915MHz / 2505MHz メモリ種類・容量 80GB HBM2e [ECC] 48GB GDDR6 [ECC] 48GB GDDR6 [ECC] メモリ性能 5120bit幅、2.0TB/s 384bit幅、864GB/s 384bit幅、960GB/s インターフェース PCI-E 5.0 x16 PCI-E 4.0 x16 PCI-E 4.0 x16 TDP 350W, Passive 350W, Passive 300W, Active 納期状況 世界中で取り合い 1~2ヶ月とのこと 在庫ありもめずらしくない 44 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
ベンチマークによる比較 v5.0の方がよりハードウェアの限界値に近い速度を出せている Star Schema Benchmark (SF=999; 875GB) CPU: AMD EPYC 7402P (24C; 2.8GHz), GPU: NVIDIA A100 [40GB; PCI-E], SSD: Intel D7-5510 (U.2; 3.84TB) x4 25,000 24,065 24,040 24,027 23,640 23,843 23,651 23,590 23,344 22,216 Query Execution Throughput [MB/s] 22,056 22,010 22,147 20,242 20,000 18,934 18,921 19,183 19,177 18,369 18,335 17,295 17,237 16,084 16,011 15,994 16,036 16,426 15,000 10,000 5,000 3,848 3,924 3,974 4,686 5,044 5,218 3,948 4,379 4,400 3,346 2,747 1,879 1,853 0 Q1_1 Q1_2 Q1_3 Q2_1 Q2_2 PostgreSQL v15.3 (Heap) 45 Q2_3 Q3_1 PG-Strom [v3.5] Q3_2 Q3_3 Q3_4 PG-Strom [v5.0] 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』 Q4_1 Q4_2 Q4_3
ハードウェア構成例 • 1GPU構成 1CPU + 1GPU + 4xNVME-SSD ➔ 20GB/s程度のデータ処理能力 • 2GPU構成 1CPU + 2GPU + 8xNVME-SSD ➔ 40GB/s程度のデータ処理能力 1GPU構成 46 2GPU構成 サーバ筺体 Supermicro AS-2015HS-TNR CPU AMD EPYC 9254 (24C, 2.9GHz) x1 RAM 16GB DDR5 4800 DIMM x12 (total: 192GB) GPU NVIDIA L40s (48GB, PCI-E) x1 NVIDIA L40s (48GB, PCI-E) x2 NVME PCI-E 4.0対応品 (U.2) x4 PCI-E 4.0対応品 (U.2) x8 HDD M.2 1.0TB NVME-SSD (OS区画用) Network 内蔵AIOM 10Gb-Ethernet (2-ports) OS Red Hat Enterprise Linux 8.x, 9.x + CUDA Toolkit 12.2 以降 DBMS PostgreSQL v15, v16 + PG-Strom v5.0以降 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
まとめ 47 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
まとめ ▌GPUの性質とPG-Stromの歴史 GPUはメモリからデータをプロセッサに流し込んで並列処理。 2011年のPGconfで聞いた講演をきっかけに作ってみた。(2012年) CustomScan APIの標準化と、SSD-to-GPU Direct機構が大きな転機。 ▌PG-Stromの特徴と課題 SQLからGPUコード(CUDA C++)を自動生成してビルド GPU-Direct SQL機構、Apache Arrow対応、GPU-Cache機構 CUDAがリソースを喰いすぎ、初期化に時間を使いすぎ ▌PG-Strom v5.0では CUDA Contextを常駐プロセス(GPU Service)だけに持たせる CUDA C++ではなく、独自の疑似命令コードで命令を定義 Coalesced Memory Accessを意識したデータ構造 ➔ 安定性、保守性、およびミドルエンドGPUでの実行性能を意識した バージョン 48 2024-03-15セミナー 『PG-Strom v5.0 ~変わったこと、できること~』
オモシロ技術を、カタチにする。