Upgrade to Pro — share decks privately, control downloads, hide ads and more …

日本発のOSS爆速DB「PG-Strom」開発の歴史と展望

Avatar for KaiGai Kohei KaiGai Kohei
September 23, 2025

 日本発のOSS爆速DB「PG-Strom」開発の歴史と展望

2025-09-06 Open Developers Conference 2025での発表資料です。
・PG-Stromを開発するまでの背景
・PG-Strom中核機能と今後の展望
について、ご紹介しています。

Avatar for KaiGai Kohei

KaiGai Kohei

September 23, 2025
Tweet

More Decks by KaiGai Kohei

Other Decks in Technology

Transcript

  1. 自己紹介 講師略歴 ✓ 海外 浩平(KaiGai Kohei) ✓ ヘテロDB株式会社 チーフアーキテクト兼CEO ✓

    筑波大学情報学類卒、同大学院 経営・政策科学研究科修了 ✓ 2003年よりNEC勤務。主にLinux kernelやPostgreSQLのコア機能開発に 従事。主にセキュリティやFDW/CSPに関する機能強化で、本家の 開発者コミュニティにも数多くの貢献。 (2007年 未踏ソフトにて「天才プログラマ―」認定、など) ✓ 2012年頃より、GPUを用いたPostgreSQL高速化モジュールである PG-Stromを開発。以降、GPUとは10年以上の付き合い。 ✓ 2017年、HeteroDB社を設立しPG-Stromの事業化に取り組む。 HeteroDB社について  設立: 2017年7月  所在地: 東京都品川区  ミッション: ヘテロジニアスコンピューティング技術を データベース領域に適用し、誰もが使いやすく、 安価で高速なデータ分析基盤を提供する。  PG-Stromエンタープライズ版の開発&販売のほか、 関連技術領域での技術サービスを行っております。 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 2
  2. 本日、お話しする事 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 3 ▌PG-Stromを開発するまでの背景  自分とOSS(オープンソースソフトウェア)の関りについて。  SELinuxを扱っていた時の挫折  GPU・CUDAとの出会い

    ▌PG-Stromの中核機能と今後の展望  GPU-Direct SQL機構  現在進行中・今後の新機能について セッション概要より: GPUを活用しデータ検索を爆速化する「PG-Strom」は、日本人が開発を行っている純国産OSSで す。その開発の経緯と、爆速化の秘密を開発者自ら解説します。ますます肥大化するデータの 分析基盤としてのGPU活用技術の詳細はもちろん、日本から如何にしてグローバルに活用され るOSSを生み出していくか、そのヒントを開発者自らの経験を元にお話します。
  3. Linux kernel開発者コミュニティとの出会い(1/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 4 ▌内定先/配属先  『スパコン向けOS開発』のポジションで内定  HPC事業部・エンタープライズLinux-Gに配属 ➔

    当時、ベクトル型スパコン(SXシリーズ)の ファイルサーバとして、64bit CPUである Itanium 2搭載サーバを製品化 ▌当時の世相  x86_64はまだ世に出ていなかった。  64bitのエンプラ向けは Itanium (IA64) という 事で、Intel, HP, NEC, Fujitsuなどが共同で Linux kernelを開発(2001~; Atlas Project) ➔ 自社のハードを売るために、自社サーバで 動作する Linux kernel の開発が必要。 ▌新人のぼくがやってた事  Linux kernelのソースコードをひたすら読む  クラッシュダンプを眺めて、障害原因を探る  その他、部門内のローカルサーバのお守り ベクトル型スパコン SX-6 Technology: 150 nm CPU Freq: 500 MHz CPU Perf: 8.0 GFlops Memory Band: 32.0GB/sec スカラ型サーバ TX-7 CPU: Itanium 2 (1.0GHz) (max 32way) RAM: ~128GB OS: Windows, HP-UX, NEC IA-64 Linux Red Hat Enterprise Linux 4 計算ノード ファイルサーバ ここの開発・保守を する部隊 2003
  4. Linux kernel開発者コミュニティとの出会い(2/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 5 Linux 2.6がやって来る!!➔ SELinuxの調査を任されると…。 https://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.11 ▌Red Hat

    Enterprise Linux 4対応  Linux kernel v2.6の新機能 ✓ O(1)スケジューラ、NUMA対応 ✓ bio(Block I/O)、aio(Asynchronous I/O) ✓ SELinux, Ext4, …等々  SELinuxにトンデモない性能劣化を 引き起こす実装を発見。 ▌開発者コミュニティへ この時の実装では、SELinuxのポリシー チェックは排他ロック(spinlock)下で 行われていた。 ➔ これをRCUを使って置き換え、CPU数が 多い環境でのスケーラビリティを確保 する提案。 ➔ 何度か実装し直したものの、 Stephen Smalley (NSA)や、James Morris (Red Hat) らの協力を得てメインライン化。 2004
  5. [補足] RCU (Read Copy Update) について 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 6 リストを更新する際にロックを使う場合 RCUによるリスト更新

    LOCK LOCK LOCK LOCK Writerのみ止める next next ➔ Read-mostlyなデータ参照に向く排他方式として、Linux kernel v2.6で対応した 新機能で、SELinuxのポリシーチェックにはドンピシャ
  6. Linux kernel開発者コミュニティとの出会い(3/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 7 ▌開発者コミュニティとは  その技術領域に強い関心を持って、 日々、改良・発展に取り組む人の 集まり。 

    技術のコンセンサスを作る ➔ そこに居ないと、合意形成に加わる ことができない。 一定の貢献(contribution)を続け る事が重要。  開発だけではなく、パッケージの 保守や、ドキュメントの整備、 イベントの運営などによって コミュニティに参加し、存在感を 発揮している人もいる。 当時、50通近くメールのやり取りがあり、Stephen Smalley(SELinuxの作者)、 James Morris(SELinuxのメンテナー)、Paul.E McKenney(RCUの作者)らの 協力を得て数回のリテイクと、10回程度の微修正を経て、Linus Torvaldsの 管理するメインラインへカーネルへ移行。 2004
  7. SE-PostgreSQLと”Innovative Portion”(1/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 8 SQLパーサ オプティマイザ エグゼキュータ クエリ木 (内部形式) 実行計画

    SQL構文 問い合わせ結果 buffer manager transaction control metadata cache IPC & Lock index access transaction logs sepgsql モジュール SELinux アクセス 可否? allowed / denied object_access_hook()
  8. SE-PostgreSQLと”Innovative Portion”(2/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 9 ▌SE-PostgreSQLの標準機能化に付随して 拡張された本体側機能  Object Access Hook機構

     ClientAuthentication hook(認証フック)  Security Barrier ViewとLeakproof関数  行レベルアクセス制御  Large Objectへの権限付与  SECURITY LABELコマンド ➔ sepgsqlモジュールだけではなく、 他の拡張モジュールの共通インフラと なるものを共通化。 contrib/sepgsql 以下のスケールは5000行程度 PostgreSQL全体のスケールは180万行程度 (全体の僅か0.27%程度の拡張機能)
  9. [補足] Security Barrier ViewとLeakproof関数(1/2) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 10 postgres=# SELECT * FROM

    customer; cid | cname | cmail | cpasswd -----+-------+-------------------+---------- 101 | alice | [email protected] | abcdef 102 | bob | [email protected] | xyz123 103 | eve | [email protected] | deadbeaf (3 rows) postgres=# CREATE VIEW my_account AS SELECT * FROM customer WHERE cname = getpgusername(); CREATE VIEW postgres=# GRANT SELECT ON my_account TO public; GRANT ~ 一般ユーザの権限でログイン ~ postgres=> CREATE FUNCTION f_leak(text) RETURNS bool LANGUAGE plpgsql COST 0.00000001 AS 'BEGIN RAISE NOTICE ''f_leak => %'', $1; RETURN true; END'; CREATE FUNCTION postgres=> SELECT * FROM my_account WHERE f_leak(cmail); NOTICE: f_leak => [email protected] NOTICE: f_leak => [email protected] NOTICE: f_leak => [email protected] cid | cname | cmail | cpasswd -----+-------+-------------------+--------- 101 | alice | [email protected] | abcdef (1 row) ユーザー名が一致している 行しか見えないぞ! おい!何か見えてるぞ! (ぴえん)
  10. [補足] Security Barrier ViewとLeakproof関数(2/2) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 11 postgres=> EXPLAIN SELECT *

    FROM my_account WHERE f_leak(cmail); QUERY PLAN ----------------------------------------------------------------- Seq Scan on customer (cost=0.00..20.85 rows=1 width=100) Filter: (f_leak(cmail) AND (cname = (getpgusername())::text)) (2 rows) postgres=# CREATE VIEW my_account_secure WITH (security_barrier) AS SELECT * FROM customer WHERE cname = getpgusername(); CREATE VIEW postgres=# GRANT SELECT ON my_credit_secure TO public; GRANT postgres=> SELECT * FROM my_account_secure WHERE f_leak(cmail); NOTICE: f_leak => [email protected] cid | cname | cmail | cpasswd -----+-------+-------------------+--------- 101 | alice | [email protected] | abcdef (1 row) postgres=> EXPLAIN SELECT * FROM my_account_secure WHERE f_leak(cmail); QUERY PLAN ------------------------------------------------------------------------- Subquery Scan on my_account_secure (cost=0.00..20.88 rows=1 width=100) Filter: f_leak(my_account_secure.cmail) -> Seq Scan on customer (cost=0.00..20.85 rows=3 width=100) Filter: (cname = (getpgusername())::text) (4 rows) f_leak()を先に実行している! (マジか!?)
  11. OSSを活用する上でのデメリットは? 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 14 ▌合意形成には時間がかかる  特に問題意識を共有する人が少ない場合は、合意形成や再設計で年単位の 時間がかかる事も。  それを許容できる事業環境やスケジュールであるかどうか。 

    非互換の独自設計のままユーザ先に出荷したら、並行メンテナンスの悪夢…。 PostgreSQLコミュニティへ はじめてSE-PostgreSQLの アイデアを投げたのは 2007年4月 メインライン機能として マージされたのは 2011年1月
  12. PostgreSQLにGPUを試そうとしたきっかけ ▌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列 E列 幅の小さいデータでも、 大量の行を並べれば 長大なBLOBと同じく GPU並列処理が効くのでは? 2011 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 17
  13. GPU(Graphics Processing Unit)とはどんなプロセッサなのか? 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 18 元々は3Dゲームでポリゴンの座標を高速に計算するためのデバイス ➔ 汎用計算にも安く使えるという事で、HPCや機械学習の分野でも スーパーコンピュータ (東京工業大学

    TSUBAME3.0) CG(Computer Graphics) 機械学習 数百~数千コアの並列処理ユニットと、TB/sを越える帯域のメモリを搭載。 大量の計算処理を得意とするが、専用のS/Wやアルゴリズムが必要。 CUDA Toolkitによって容易にSW開発が可能となった。 シミュレーション NVIDIA H100 RTX 4090Ti 3D Gaming
  14. CPUとGPUの設計思想の違い(1/3) GPU DRAM DRAM Cache Cache ✓ データアクセスの局所性 ✓ キャッシュ&高クロック

    ➔ 処理のレイテンシに優位性 ✓ 次から次へと、データを演算器に 流し込む事に特化した構造。 ✓ 広帯域メモリ&大容量レジスタ ➔ 処理のスループットに優位性 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 19 小回りが利くが輸送力は 小さな乗用車のような プロセッサ 使える状況が限られるが、 大量輸送が可能な 高速鉄道のような プロセッサ
  15. CPUとGPUの設計思想の違い(2/3) LZ77圧縮アルゴリズムの例 (F,8,’capybara’) (T,4,4) ’c’ ’a’ ’p’ ’y’ ’b’ ’a’

    ’r’ ’a’ (T,4,3) (T,14,3) ’c’ ’a’ ’p’ ’y’ ’b’ ’a’ ’r’ ’a’ ’b’ ’a’ ’r’ ’a’ ’c’ ’a’ ’p’ ’y’ ’b’ ’a’ ’r’ ’a’ ’b’ ’a’ ’r’ ’a’ ’b’ ’a’ ’r’ ’c’ ’a’ ’p’ ’y’ ’b’ ’a’ ’r’ ’a’ ’b’ ’a’ ’r’ ’a’ ’b’ ’a’ ’r’ ’a’ ’p’ ’y’ 4文字戻って4文字を追記 4文字戻って3文字を追記 14文字戻って3文字を追記 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 20
  16. CPUとGPUの設計思想の違い(3/3) 行列積の計算の例 x0 x1 x2 x3 x4 x5 x6 x7

    xk xn × × × × × × × × × × y0 y1 y2 y3 y4 y5 y6 y7 yk yn + + + + + + + + 計算の依存性無し 計算の依存性は最小限 隣の要素の計算が 終わっていれば、 加算を実行可能 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 21
  17. コレって検索ワークロードに似ていない? テーブルスキャンの方向 x_val = 123 x_val = 234 x_val =

    345 x_val = 456 x_val = 567 WHERE x_val % 2 = 1 〇 × 〇 × 〇 • • • • • GPUコア ✓ DBテーブルをある種のベクトルと見なせば、 一度の処理サイクルで数千~万行の処理が可能に 行列計算の場合 テーブルスキャンの場合 𝑣 × 𝐴 v0 v1 v2 v3 vn-4 vn-3 vn-2 vn-1 ak,0 ak,1 ak,2 ak,3 ak,n-4 ak,n-3 ak,n-2 ak,n-1 × × × × × × × × ベクトル v 行列A 異なるデータに 同じ演算を多数実行 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 22
  18. 実際に作ってみた(2/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 24 void pgstrom_get_foreign_paths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid)

    { : /* check whether GPU/CPU executable qualifier, or not */ foreach (cell, baserel->baserestrictinfo) { RestrictInfo *rinfo = lfirst(cell); if (is_gpu_executable_qual(baserel, rinfo)) gpu_quals = lappend(gpu_quals, rinfo); : } /* Generate command series executed with GPU/CPU, if any */ if (gpu_quals) { cmds_bytea = make_gpu_commands(gpu_quals, &gpu_cols); defel = makeDefElem("gpu_cmds", (Node *) cmds_bytea); private = lappend(private, defel); } : f_path = create_foreignscan_path(root, baserel, ...); add_path(baserel, (Path *) f_path); } 2012 WHERE句がGPUで実行可能か どうかをチェックする。 GPU用のWHERE句処理関数を 自動生成する。 (当時は素のCUDA C++コードを 生成し、実行時ビルドしていた) 実行コストを計算して、 PostgreSQLのオプティマイザに GPUを使うパスを登録する。
  19. 実際に作ってみた(3/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 25 ▌FDW: Foreign Data Wrapper  v8.4からある機能で、外部のデータソースをテーブルのように読み出す機能 

    『エグゼキュータを乗っ取る』ために利用できた PostgreSQLの実行計画作成、クエリ実行の流れ 2012 SQLパーサ オプティマイザ エグゼキュータ クエリ木 (内部形式) 実行計画 SQL構文 問い合わせ結果 buffer manager transaction control metadata cache IPC & Lock index access transaction logs GetForeignPaths() GetForeignPlan() FDW モジュール • 実行計画を作成 • 実行開始 • 次の1行を返す • 実行終了 BeginForeignScan() IterateForeignScan() EndForeignScan() External RDBMS CSV Files
  20. 当時の課題 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 26 ▌FDWは読み込み専用だった  データのロードには専用関数を用いていた。  INSERT/UPDATE/DELETEが使用できない ➔ 後に

    “Writable Foreign Table” 機能を提案し、標準機能化したとはいえ…。 ▌FDWだとDDL構文が異なる  外部テーブルを作成するには CREATE FOREIGN TABLE name ( … ) SERVER … OPTIONS (…); と、やたらおまじないが多い。  SQL構文が互換でないと、アプリケーションが利用できない場合も。 ➔ 『利用できない』にはクエリの修正や再検証が必要も含む。 ▌GPU-Scanだけでは応用範囲が狭い  JOINやGroup-BYなどを高速化するにはどうするか?
  21. Custom-Scan APIs(1/5) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 27 PostgreSQLのテーブルを Scan/Join する代替の方法を定義する 2014 SQLパーサ オプティマイザ

    エグゼキュータ クエリ木 (内部形式) 実行計画 SQL構文 問い合わせ結果 buffer manager transaction control metadata cache IPC & Lock index access transaction logs 拡張モジュール • 実行計画を作成・登録 • 実行開始 • 次の1行を返す • 実行終了 set_rel_pathlist_hook set_join_pathlist_hook create_upper_paths_hook それぞれPostgreSQLのテーブルを Scan/Join/Group-byするタイミングで 呼び出されるフックを追加 ExecCustomScan() どう実装するかは 拡張モジュールが 任意に決める事が できる。
  22. Custom-Scan APIs(2/5) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 28 ssbm=# explain select sum(lo_revenue), d_year, p_brand1

    from lineorder, date1, part, supplier where lo_orderdate = d_datekey and lo_partkey = p_partkey and lo_suppkey = s_suppkey and p_category = 'MFGR#12’ and s_region = 'AMERICA’ group by d_year, p_brand1; QUERY PLAN --------------------------------------------------------------------------------------------------- HashAggregate (cost=192049053.77..192049141.27 rows=7000 width=46) Group Key: date1.d_year, part.p_brand1 -> Hash Join (cost=373962.46..191695451.95 rows=47146910 width=20) Hash Cond: (lineorder.lo_orderdate = date1.d_datekey) -> Hash Join (cost=373857.95..191571381.58 rows=47146910 width=20) Hash Cond: (lineorder.lo_suppkey = supplier.s_suppkey) -> Hash Join (cost=55265.84..190631708.88 rows=236602030 width=26) Hash Cond: (lineorder.lo_partkey = part.p_partkey) -> Seq Scan on lineorder (cost=0.00..174826341.12 rows=6000026112 width=20) -> Hash (cost=54280.00..54280.00 rows=78867 width=14) -> Seq Scan on part (cost=0.00..54280.00 rows=78867 width=14) Filter: (p_category = 'MFGR#12'::bpchar) -> Hash (cost=293684.47..293684.47 rows=1992611 width=6) -> Seq Scan on supplier (cost=0.00..293684.47 rows=1992611 width=6) Filter: (s_region = 'AMERICA'::bpchar) -> Hash (cost=72.56..72.56 rows=2556 width=8) -> Seq Scan on date1 (cost=0.00..72.56 rows=2556 width=8) (17 rows) 2014
  23. Custom-Scan APIs(3/5) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 29 ssbm=# explain select sum(lo_revenue), d_year, p_brand1

    from lineorder, date1, part, supplier where lo_orderdate = d_datekey and lo_partkey = p_partkey and lo_suppkey = s_suppkey and p_category = 'MFGR#12’ and s_region = 'AMERICA’ group by d_year, p_brand1; QUERY PLAN ------------------------------------------------------------------------------------------------------------ HashAggregate (cost=30939287.03..30939374.53 rows=7000 width=46) Group Key: date1.d_year, part.p_brand1 -> Custom Scan (GpuPreAgg) on lineorder (cost=30939164.53..30939234.53 rows=7000 width=46) GPU Projection: pgstrom.psum(lineorder.lo_revenue), date1.d_year, part.p_brand1 GPU Join Quals [1]: (part.p_partkey = lineorder.lo_partkey) ... [nrows: 6000026000 -> 236602000] GPU Outer Hash [1]: lineorder.lo_partkey GPU Inner Hash [1]: part.p_partkey GPU Join Quals [2]: (supplier.s_suppkey = lineorder.lo_suppkey) ... [nrows: 236602000 -> 47146910] GPU Outer Hash [2]: lineorder.lo_suppkey GPU Inner Hash [2]: supplier.s_suppkey GPU Join Quals [3]: (date1.d_datekey = lineorder.lo_orderdate) ... [nrows: 47146910 -> 47146910] GPU Outer Hash [3]: lineorder.lo_orderdate GPU Inner Hash [3]: date1.d_datekey GPU Group Key: date1.d_year, part.p_brand1 GPU-Direct SQL: enabled (N=2,GPU0,1) -> Custom Scan (GpuScan) on part (cost=100.00..30481.17 rows=78867 width=14) GPU Projection: p_brand1, p_partkey GPU Scan Quals: (p_category = 'MFGR#12'::bpchar) [rows: 2000000 -> 78867] GPU-Direct SQL: enabled (N=2,GPU0,1) -> Custom Scan (GpuScan) on supplier (cost=100.00..190276.56 rows=1992611 width=6) GPU Projection: s_suppkey GPU Scan Quals: (s_region = 'AMERICA'::bpchar) [rows: 9999718 -> 1992611] GPU-Direct SQL: enabled (N=2,GPU0,1) -> Seq Scan on date1 (cost=0.00..72.56 rows=2556 width=8) (24 rows) 2014
  24. Custom-Scan APIs(4/5) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 30 ▌FDWとCustomScanの違い  FDWはデータソース(What)を多様化する。  CustomScanはPostgreSQLテーブルを読み出す 方法(How)を多様化する。

    ▌開発の副産物  JOINのパスを追加するためのフック  GROUP-BY等のパスを追加するためのフック ➔postgres_fdwのremote join pushdownなど  Background worker process ➔ CUDA C++のコードを実行時コンパイルするために 提案した機能 2014
  25. GPU-Direct SQLの着想と開発(1/5) GPUコア GPU Device Memory CPU Host Memory ストレージ

    (HDD/SSD) CPU 720GB/s 16GB/s 0.5GB/s 60GB/s NVME-SSD 一台あたり 3GB/s (当時の)PG-Stromを含む、 GPU-DBはデータがオンメモリ前提 ストレージに落ちたら「負け」 一方この頃、NVME-SSD製品が登場 安価な高速SSDがブレイクの兆し。 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 33 2015
  26. GPU-Direct SQLの着想と開発(2/5) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 34 DMAコントローラは物理アドレスに対してデータを投げる 物理アドレス空間 論理アドレス空間 process-X process-Y 0x000000000000

    PCIデバイス 0x037000000000 PCI-E Bar1 Linux kernel 0x038000000000 NVME-SSD上のブロック xxx 番から 20ブロック分を読み出して、 物理アドレス0x00... へと転送せよ NVME-SSD上のブロック xxx 番から 20ブロック分を読み出して、 物理アドレス0x37... へと転送せよ NVME READ BlkNo: xxxx Length: 20 Dest: 0x00.... NVME READ BlkNo: xxxx Length: xxx Dest: 0x037.... 2015
  27. GPU-Direct SQLの着想と開発(3/5) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 35 static int ioctl_map_gpu_memory(StromCmd__MapGpuMemory __user *uarg) {

    mapped_gpu_memory *mgmem; : if (copy_from_user(&karg, uarg, sizeof(karg))) return -EFAULT; mgmem = kmalloc(sizeof(mapped_gpu_memory), GFP_KERNEL); if (!mgmem) return -ENOMEM; map_address = karg.vaddress & GPU_BOUND_MASK; map_offset = karg.vaddress & GPU_BOUND_OFFSET; handle = (unsigned long) mgmem; INIT_LIST_HEAD(&mgmem->chain); mgmem->hindex = strom_mapped_gpu_memory_index(handle); mgmem->refcnt = 0; mgmem->owner = current_euid(); mgmem->handle = handle; mgmem->map_address = map_address; mgmem->map_offset = map_offset; mgmem->map_length = map_offset + karg.length; mgmem->wait_task = NULL; : rc = __nvidia_p2p_get_pages(0, /* p2p_token; deprecated */ 0, /* va_space_token; deprecated */ mgmem->map_address, mgmem->map_length, &mgmem->page_table, callback_release_mapped_gpu_memory, mgmem); : } nvidiaドライバのkernel APIを用いて、 GPUデバイスメモリの論理⇒物理変換 それを利用して、NVME READリクエス トを偽装してドライブに送出する。 2015
  28. GPU-Direct SQLの着想と開発(4/5) ✓ GPU-Direct SQL(当時は SSD-to-GPU Direct SQL)により、メモリサイズを越えた 大量データ(数TB~)を処理する事が可能に。 ➔

    他のGPU-DB製品と比べ、この特徴がPG-Stromを「ストレージとの密結合」という “異質な”進化をするきっかけに。 実験用に購入した Intel SSD 750 (400GB) の 理論帯域まで出ている (!) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 36 2016
  29. GPU-Direct SQL機構(1/4) PCI-E Bus Buffer Copy Buffer Copy SCAN JOIN

    GROUP BY Storage Block Read 大量の ”ゴミデータ” も含む 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 38
  30. GPU-Direct SQL機構(2/4) P2P-DMAを利用し、NVME-SSDとGPUを直結してデータ転送 PCI-E Bus SCAN JOIN GROUP BY Storage

    Block Read by NVIDIA GPUDirect Storage P2P-DMA P2P-DMA : Peer-to-Peer Direct Memory Access 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 39
  31. GPU-Direct SQL機構(3/4) Supermicro 4029GP-TRT CPU: Xeon Gold 6226 (2.7GHz, 12C)

    x2 RAM: 192GB (16GB DDR4-2666) x12 GPU: NVIDIA Tesla V100 (5120C, 16GB) x4 SSD: Intel SSD DC P4510 (1.0TB, U.2) x16 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 40 2019
  32. GPU-Direct SQL機構(4/4) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 41 タスクを細分化し、I/Oと計算を並行させてリソースを使い尽くす GPU0 GPU1 ファイルの オープン (必要なら)

    ファイルの ダイレクト 読み出し GPUでの SQL処理の 実行 終了 ステータス 確認 ファイルの オープン (必要なら) ファイルの ダイレクト 読み出し GPUでの SQL処理の 実行 終了 ステータス 確認 ファイルの オープン (必要なら) ファイルの ダイレクト 読み出し GPUでの SQL処理の 実行 終了 ステータス 確認 ファイルの オープン (必要なら) ファイルの ダイレクト 読み出し GPUでの SQL処理の 実行 終了 ステータス 確認 ファイルの オープン (必要なら) ファイルの ダイレクト 読み出し GPUでの SQL処理の 実行 終了 ステータス 確認 ファイルの オープン (必要なら) ファイルの ダイレクト 読み出し GPUでの SQL処理の 実行 終了 ステータス 確認 PG-Strom GPU Service (background worker process) GPU0 Task Queue GPU1 Task Queue PostgreSQL Parallel worker process PostgreSQL Backend process PostgreSQL Backend process マルチスレッド処理
  33. Apache Arrowへの対応(1/3) ETL OLTP OLAP 伝統的なOLTP&OLAPシステム - データはDBシステムの内側で生成される Data Creation

    IoT/M2M時代 - データはDBシステムの外側で生成される Log processing BI Tools BI Tools Gateway Server Data Creation Data Creation Many Devices 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 43 DBシステムへのデータのインポートが、集計処理以上に時間のかかる処理に! Data Import Import! 2019
  34. Apache Arrowへの対応(2/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 44 ▌Arrow形式の特徴  列指向で分析用途向けに設計されたデータ形式  アプリケーションによらず、共通のデータ交換形式として利用可能 

    整数、実数、日付時刻、文字列など基本的なデータ型を定義  更新・削除は無理だが、追記に強い(➔ ログデータに向いた形式) NVIDIA GPU PostgreSQL / PG-Strom 2019
  35. Apache Arrowへの対応(3/3) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 45 ▌なぜApache Arrow形式がログデータ処理に適しているのか?  被参照列のみ読み出すため、I/O量が少なくて済む  GPUメモリバスの特性から、プロセッサ実行効率が高い

     Read-onlyデータなので、実行時のMVCC検査を行う必要がない SSD-to-GPU Direct SQL機構を使って、被参照列だけを転送する。 PCIe Bus NVMe SSD GPU SSD-to-GPU P2P DMA WHERE-clause JOIN GROUP BY クエリの被参照列のみ、 ダイレクトデータ転送 Apache Arrow形式を解釈し、 データを取り出せるよう GPUコード側での対応。 小規模の処理結果だけを PostgreSQLデータ形式で返す Results metadata 2019
  36. Arrow_Fdw外部テーブルを使用した場合のパフォーマンス ▌GPUに転送すべきデータ量の違いにより処理速度のブレが大きいものの、 行データ(heap)と比較して、全体的に非常に高いデータ処理能力を発揮。 ▌Arrowファイルの内容はSSBMのlineorderテーブルの複製(同一内容) 35.4 36.6 36.9 41.0 44.7 45.9

    18.0 31.0 39.9 40.2 16.9 19.3 19.3 148.3 148.1 148.3 146.0 137.9 146.8 141.3 145.9 146.8 146.9 141.5 140.9 145.2 1,092.3 1,112.8 1,115.8 736.7 899.4 954.0 467.7 637.3 864.0 1,062.2 488.0 494.5 707.4 0 200 400 600 800 1,000 1,200 Q1_1 Q1_2 Q1_3 Q2_1 Q2_2 Q2_3 Q3_1 Q3_2 Q3_3 Q3_4 Q4_1 Q4_2 Q4_3 Query Execution Throughput [百万行/秒] PostgreSQL v16 [Heap] PG-Strom v5.3 [Heap] PG-Strom v5.3 [Arrow] 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 46
  37. Arrow_Fdwによる外部テーブルの定義(1/2) postgres=# drop foreign table f_mytest ; DROP FOREIGN TABLE

    postgres=# CREATE FOREIGN TABLE f_mytest ( id int, ts timestamp, x float8, y text, z numeric ) SERVER arrow_fdw OPTIONS (file '/tmp/mytest.arrow'); CREATE FOREIGN TABLE postgres=# SELECT * FROM f_mytest; id | ts | x | y | z ----+----------------------------+--------------------+--------------+--------- 1 | 2022-08-02 00:34:44.210589 | 77.4344383633856 | 65ac7f6 | 38.6218 2 | 2019-05-11 03:06:16.353798 | 95.33235230265761 | 9105319395 | 51.8267 3 | 2015-01-04 11:02:25.66779 | 93.67415248121794 | b56930f7834 | 84.9033 : : : : : 24 | 2022-09-24 06:26:02.058316 | 17.668632938372266 | c5e35 | 55.9739 25 | 2016-08-08 18:16:12.248363 | 92.2211769466387 | fa889dd51692 | 19.246 (25 rows) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 47
  38. Arrow_Fdwによる外部テーブルの定義(2/2) ▌構文 IMPORT FOREIGN SCHEMA table_name FROM SERVER arrow_fdw INTO

    public OPTIONS (file ‘/path/to/arrow_file’);  Arrowファイルのスキーマ定義情報から、PostgreSQLのテーブル定義を自動生成する。 postgres=# IMPORT FOREIGN SCHEMA f_mytest FROM SERVER arrow_fdw INTO public OPTIONS (file '/opt/arrow/mytest.arrow'); IMPORT FOREIGN SCHEMA postgres=# ¥d f_mytest Foreign table "public.f_mytest" Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------------+-----------+----------+---------+------------- id | integer | | | | ts | timestamp without time zone | | | | x | double precision | | | | y | text | | | | z | numeric | | | | Server: arrow_fdw FDW options: (file '/opt/arrow/mytest.arrow’) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 48
  39. Arrowテーブルを組み込んだデータベース構造(1/2) ログデータ トランザクションデータ (PostgreSQL Heap形式) 肥大化 古いデータを Arrow形式に変換 pg2arrow: SELECT

    * FROM my_table WHERE ymd >= ‘2023-01-01’ AND ymd < ‘2024-01-01’ すごく古いデータは、gzipなどで固めて バックアップ用ストレージへ テーブルパーティション mytable_2022.arrow mytable_2023.arrow 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 49
  40. Arrowテーブルを組み込んだデータベース構造(2/2) $ ls -l /opt/arrow/monthly/ total 337074788 -rw-r--r--. 1 kaigai

    kaigai 967199318 Dec 14 00:17 f_lineorder_199301_AIR.arrow -rw-r--r--. 1 kaigai kaigai 966790870 Dec 14 00:18 f_lineorder_199301_FOB.arrow -rw-r--r--. 1 kaigai kaigai 978921494 Dec 14 00:19 f_lineorder_199301_MAIL.arrow -rw-r--r--. 1 kaigai kaigai 978374102 Dec 14 00:20 f_lineorder_199301_RAIL.arrow -rw-r--r--. 1 kaigai kaigai 978857494 Dec 14 00:22 f_lineorder_199301_SHIP.arrow -rw-r--r--. 1 kaigai kaigai 989774806 Dec 14 00:23 f_lineorder_199301_TRUCK.arrow -rw-r--r--. 1 kaigai kaigai 873871318 Dec 14 00:24 f_lineorder_199302_AIR.arrow -rw-r--r--. 1 kaigai kaigai 873760598 Dec 14 00:25 f_lineorder_199302_FOB.arrow -rw-r--r--. 1 kaigai kaigai 883919318 Dec 14 00:26 f_lineorder_199302_MAIL.arrow -rw-r--r--. 1 kaigai kaigai 884077078 Dec 14 00:27 f_lineorder_199302_RAIL.arrow -rw-r--r--. 1 kaigai kaigai 883877142 Dec 14 00:28 f_lineorder_199302_SHIP.arrow -rw-r--r--. 1 kaigai kaigai 893281622 Dec 14 00:30 f_lineorder_199302_TRUCK.arrow -rw-r--r--. 1 kaigai kaigai 967705878 Dec 14 00:31 f_lineorder_199303_AIR.arrow -rw-r--r--. 1 kaigai kaigai 967453078 Dec 14 00:32 f_lineorder_199303_FOB.arrow -rw-r--r--. 1 kaigai kaigai 978963094 Dec 14 00:33 f_lineorder_199303_MAIL.arrow -rw-r--r--. 1 kaigai kaigai 978954454 Dec 14 00:34 f_lineorder_199303_RAIL.arrow -rw-r--r--. 1 kaigai kaigai 978754966 Dec 14 00:36 f_lineorder_199303_SHIP.arrow -rw-r--r--. 1 kaigai kaigai 989493718 Dec 14 00:37 f_lineorder_199303_TRUCK.arrow -rw-r--r--. 1 kaigai kaigai 936397334 Dec 14 00:38 f_lineorder_199304_AIR.arrow -rw-r--r--. 1 kaigai kaigai 936229014 Dec 14 00:39 f_lineorder_199304_FOB.arrow -rw-r--r--. 1 kaigai kaigai 946560726 Dec 14 00:40 f_lineorder_199304_MAIL.arrow -rw-r--r--. 1 kaigai kaigai 947162198 Dec 14 00:42 f_lineorder_199304_RAIL.arrow -rw-r--r--. 1 kaigai kaigai 946814166 Dec 14 00:43 f_lineorder_199304_SHIP.arrow -rw-r--r--. 1 kaigai kaigai 957260310 Dec 14 00:44 f_lineorder_199304_TRUCK.arrow -rw-r--r--. 1 kaigai kaigai 967627350 Dec 14 00:45 f_lineorder_199305_AIR.arrow -rw-r--r--. 1 kaigai kaigai 967433046 Dec 14 00:46 f_lineorder_199305_FOB.arrow 習慣的に、ファイル名に “yyyymmdd” を付加したりしますよね? 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 50
  41. Arrow_FdwのVirtual Column機構(1/2) ssbm=# IMPORT FOREIGN SCHEMA f_lineorder_vcol FROM SERVER arrow_fdw

    INTO public OPTIONS (dir '/opt/arrow/monthly', pattern 'f_lineorder_@{year_month}_${shipmode}.arrow'); IMPORT FOREIGN SCHEMA ssbm=# ¥d f_lineorder_vcol Foreign table "public.f_lineorder_vcol" Column | Type | Collation | Nullable | Default | FDW options --------------------+--------------+-----------+----------+---------+------------------------ lo_orderkey | bigint | | | | lo_linenumber | integer | | | | lo_custkey | integer | | | | lo_partkey | integer | | | | lo_suppkey | integer | | | | lo_orderdate | integer | | | | lo_orderpriority | text | | | | lo_shippriority | character(1) | | | | lo_quantity | integer | | | | lo_extendedprice | integer | | | | lo_ordertotalprice | integer | | | | lo_discount | integer | | | | lo_revenue | integer | | | | lo_supplycost | integer | | | | lo_tax | integer | | | | lo_commit_date | text | | | | lo_shipmode | text | | | | year_month | bigint | | | | (virtual 'year_month') shipmode | text | | | | (virtual 'shipmode') Server: arrow_fdw FDW options: (dir '/opt/arrow/monthly', pattern 'f_lineorder_@{year_month}_${shipmode}.arrow') 実はArrowファイル上には存在していない列。 ファイル名の一部を列の値として読み出す 事ができる。 @{xxxx} … 数値列(bigint) ${xxxx} … 文字列(text) 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 51
  42. Arrow_FdwのVirtual Column機構(2/2) ssbm=# explain (analyze, costs off) select sum(lo_extendedprice*lo_discount) from

    f_lineorder_vcol where year_month = 199401 and lo_discount between 4 and 6 and lo_quantity between 26 and 35; QUERY PLAN -------------------------------------------------------------------------------------------------- Aggregate (actual time=123.326..123.328 rows=1 loops=1) -> Custom Scan (GpuPreAgg) on f_lineorder_vcol (actual time=123.315..123.317 rows=2 loops=1) GPU Projection: pgstrom.psum(((lo_extendedprice * lo_discount))::bigint) GPU Scan Quals: ((lo_discount >= 4) AND (lo_discount <= 6) AND (lo_quantity >= 26) AND (lo_quantity <= 35) AND (year_month = 199401)) [plan: 3914078000 -> 489, exec: 77300885 -> 4217587] referenced: lo_quantity, lo_extendedprice, lo_discount, year_month Stats-Hint: (year_month = 199401) [loaded: 28, skipped: 1416] file0: /opt/arrow/monthly/f_lineorder_199411_FOB.arrow (read: 122.30MB, size: 892.79MB) file1: /opt/arrow/monthly/f_lineorder_199406_AIR.arrow (read: 122.28MB, size: 892.68MB) file2: /opt/arrow/monthly/f_lineorder_199709_FOB.arrow (read: 122.38MB, size: 893.37MB) file3: /opt/arrow/monthly/f_lineorder_199401_RAIL.arrow (read: 126.33MB, size: 932.76MB) file4: /opt/arrow/monthly/f_lineorder_199508_TRUCK.arrow (read: 126.39MB, size: 943.73MB) : : : : file360: /opt/arrow/monthly/f_lineorder_199405_SHIP.arrow (read: 126.43MB, size: 933.48MB) GPU-Direct SQL: enabled (N=2,GPU0,1; direct=113261, ntuples=77300885) Planning Time: 4.772 ms Execution Time: 128.046 ms min/max統計情報と同じ仕組みで、明らかにマッチしないRecord Batchを読み飛ばし 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 52
  43. 現在進めている機能改良 ▌Parquet形式ファイル  Arrowと同じく、列指向の構造化データ形式。  多様なデータ圧縮オプションを持ち、IoT/M2M領域でのログデータ保存でよく 利用されている事例を聞く。 ➔ メモリ上のデータ交換中心の Apache

    Arrow とはコンテキストが異なる。 postgres=# import foreign schema weather from server arrow_fdw into public options (file '/home/kaigai/weather.parquet'); IMPORT FOREIGN SCHEMA postgres=# select "MinTemp","MaxTemp","Temp9am","Temp3pm" from weather where "MaxTemp" - "MinTemp" < 5; MinTemp | MaxTemp | Temp9am | Temp3pm ---------+---------+---------+--------- 13.3 | 15.5 | 13.5 | 14.1 16.4 | 19.4 | 16.5 | 18.3 19.9 | 22 | 20.6 | 19.6 : : : : 10.2 | 15 | 12.9 | 13.7 8.7 | 13 | 8.8 | 11.1 8.4 | 11.7 | 9.7 | 11.3 (15 rows) Parquet形式ファイルへの対応 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 53 2025?
  44. 内部アーキテクチャの改良(1/2)  PostgreSQLはマルチプロセスモデル → クライアント毎にfork(2)してバックエンドを生成  PG-Stromを使用するバックエンドプロセスは、APIの使用時に必ずCUDA Contextを生成する。 ✓ CUDA

    Context = GPU処理にとってのプロセス(リソースやスケジューリングの単位) GPU PostgreSQL Backend CUDA Context PG-Strom Postmaster Process working memory fork(2) DBクライアント 20250523爆速DBセミナー ~PG-Strom v6.0 新機能とその先の未来~ 56 2023
  45. 内部アーキテクチャの改良(1/2)  PostgreSQLはマルチプロセスモデル → クライアント毎にfork(2)してバックエンドを生成  PG-Stromを使用するバックエンドプロセスは、APIの使用時に必ずCUDA Contextを生成する。 ✓ CUDA

    Context = GPU処理にとってのプロセス(リソースやスケジューリングの単位)  CUDA Contextは存在するだけでリソースを消費する(GPUメモリ数百MB) ➔ 同時接続クライアント数が増えると地獄!! GPU PostgreSQL Backend CUDA Context PG-Strom PostgreSQL Backend CUDA Context PG-Strom PostgreSQL Backend CUDA Context PG-Strom Postmaster Process working memory working memory working memory fork(2) DBクライアント 20250523爆速DBセミナー ~PG-Strom v6.0 新機能とその先の未来~ 57 2023
  46. 内部アーキテクチャの改良(2/3)  PostgreSQLはマルチプロセスモデル → クライアント毎にfork(2)してバックエンドを生成  PG-Stromを使用するバックエンドプロセスは、APIの使用時に必ずCUDA Contextを生成する。 ✓ CUDA

    Context = GPU処理にとってのプロセス(リソースやスケジューリングの単位)  CUDA Contextは存在するだけでリソースを消費する(GPUメモリ数百MB) ➔ 同時接続クライアント数や並列処理ワーカーが増えると地獄!! GPU PostgreSQL Backend CUDA Context PG-Strom PostgreSQL Backend CUDA Context PG-Strom PostgreSQL Backend CUDA Context PG-Strom Postmaster Process working memory working memory working memory PostgreSQL Worker CUDA Context PG-Strom PostgreSQL Backend CUDA Context PG-Strom working memory working memory fork(2) 何もしなくても 消費するリソース DBクライアント 20250523爆速DBセミナー ~PG-Strom v6.0 新機能とその先の未来~ 58 2023
  47. PostgreSQL Backend 内部アーキテクチャの改良(2/3) CUDA Contextの生成ごとに消費されるワーキングメモリの節約 PG-Strom v3.x 系列 PG-Strom v5.0

    GPU PostgreSQL Backend CUDA Context PG-Strom PostgreSQL Backend CUDA Context PG-Strom PostgreSQL Backend CUDA Context PG-Strom Postmaster Process working memory working memory working memory fork(2) GPU PG-Strom PostgreSQL Backend Background Worker CUDA Context GPU Service (multi- threads) Postmaster Process working memory fork(2) PG-Strom Local connection to GPU Service ✓ コード品質やデバッグ手法に対する知見が十分で なかった時期、デバッグを容易にするメリット。 ✓ メモリコピーのコストをやや過大に見積もり。 ✓ CUDAの初期化時間(数百ms)、およびワーキン グメモリ(数百MB~1GB)の節約。 ✓ クエリ毎の内部状態を持てるようになった。 20250523爆速DBセミナー ~PG-Strom v6.0 新機能とその先の未来~ 59 2023 クエリ毎の 内部状態
  48. 内部アーキテクチャの改良(3/3) GPU-Serviceがリモートマシンでも支障はないのでは? 61 PostgreSQL Backend PG-Strom v5.0 GPU PG-Strom PostgreSQL

    Backend Background Worker CUDA Context GPU Service (multi- threads) Postmaster Process working memory fork(2) PG-Strom Local connection to GPU Service ✓ CUDA Context初期化時間、およびワーキング メモリ(数百MB~1GB)の節約。 ✓ CUDA Contextスイッチの削減とGPU使用率改善 PostgreSQL Backend PG-Strom PostgreSQL Backend Postmaster Process fork(2) PG-Strom PG-Strom v7.0(?) Remote Process GPU Service GPU NVME Cache Remote Process GPU Service GPU NVME Cache 共有ファイル システム (NFS, Lusterなど) コンテナなど利用して、 バッチ処理の時間帯だけ GPUサーバ上で稼働。 TCP/IPで接続 遠隔サーバも可能 20250523爆速DBセミナー ~PG-Strom v6.0 新機能とその先の未来~ 2026?
  49. まとめ:PG-Stromの歴史と、今後の方向性 20250906~日本発のOSS爆速DB「PG-Strom」開発の歴史と展望 62 ▌PG-Stromの歴史  元々、Linux kernelやSELinuxを扱っていた時代のモチベーション 『オープンソースに+αを加えて、ビジネスとして意味のある事をやりたい』  「セキュリティ」という切り口ではあまり上手く行かなかった。

     その頃出会ったのが GPU と並列計算。  ビッグデータのムーブメント。大量データ処理の需要が沸き上がる。  PG-Stromのユニーク機能 GPU-Direct SQLでI/Oバスの限界速度を追及。 ➔ 手ごたえを感じ、起業してこれを世に問うてみよう。 ▌今後の方向性(v7.0?)  Parquet形式への対応  DBサーバとGPUサーバの分離(リモートで動作するGPU-Service)  GPUの動的なアタッチ/デタッチ ➔ AI用途で導入が進むGPUインスタンスを、オンデマンドで必要な時だけ 間借りする形が狙い。