仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

PG-StromをUbuntuで使ってみた

注: PG-Strom 5.x以降のバージョンのPG-StromをUbuntuで動かしたい場合は、CUDA 12.2以降のバージョンをインストールしてください。この注を書いた2024/06/14時点ではCUDA 12.5.0が最新版であり、Ubuntu 20.04や22.04は対応していますがUbuntu 24.04は対応していません。


PG-Stromとは

PG-StromはCUDA、GPUとGPUDirect Storage対応したストレージを組み合わせて使うことで、 PostgreSQLの処理をスケールさせて高速化するソフトウェアです。 また、PG-StromでApache Arrow形式のデータを外部テーブルとして利用する機能も含まれます。

Apache Arrow形式はデータの読み出しがとにかく速いので、PostgreSQLで使えるとかなり データ分析が捗ります。

  • Arrow形式は必要なところだけしか読み出さないので、読み出しが高速化
  • PG-Stromは処理部分はGPUにスケールするので、CPUで動かすよりもデータ処理を高速に
  • Arrow形式のファイルを適当なところにおいて登録するだけで他のデータ同様使える
  • 他のノードにデータを転送して同様に登録するだけで移行完了という手軽さ
  • Fluentdを介して、ログデータをArrow形式にしてPG-Stromノードで分析できる

インストール方法は次のオフィシャルドキュメントがありますが、今回はUbuntu 20.04で動かしてみたいと思います。

必要なもの

今回、手元で動作確認したバージョンと組み合わせは次のとおりです。

  • Ubuntu Server 20.04.5 (20.04.6+GAカーネルでも動作することを確認)
  • CUDA 12.0.1
  • Pascal世代以降のNVIDIA GPUでCUDAサポートのGPU
  • PostgreSQL 15

CUDA 11.4 < CUDA 12.0.1をインストール

PG-StromはCUDA 11.4以降のCUDAを利用します。現在テストされているバージョンはCUDA 12までのバージョンです(12.0.1も含む)。 この範囲のバージョンでかつ、サポートされているOS、カーネルの組み合わせでインストールしてください。 正しくない組み合わせではそもそもCUDAが正常インストールできません。インストールするバージョンのCUDAのドキュメント を確認してください。

事前に開発ツールなどをインストールします。

sudo apt-get install build-essential libicu-dev
sudo systemctl set-default multi-user.target
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

次にCUDAをインストールします。次はUbuntu Serverに最低限のCUDA環境をセットアップする例です。

wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/cuda-ubuntu2004.pin
sudo mv cuda-ubuntu2004.pin /etc/apt/preferences.d/cuda-repository-pin-600
wget https://developer.download.nvidia.com/compute/cuda/12.0.1/local_installers/cuda-repo-ubuntu2004-12-0-local_12.0.1-525.85.12-1_amd64.deb
sudo dpkg -i cuda-repo-ubuntu2004-12-0-local_12.0.1-525.85.12-1_amd64.deb
sudo cp /var/cuda-repo-ubuntu2004-12-0-local/cuda-*-keyring.gpg /usr/share/keyrings/
sudo apt-get update
sudo apt-get install --no-install-recommends cuda

再起動とドライバーの確認

ここで一旦再起動して、再起動後にドライバーが正常に導入されたかコマンドを実行して確認します。

sudo reboot
...
nvidia-smi (実行してエラーが出ないことを確認)

PostgreSQL 15をインストール

PostgreSQL Serverをインストールします。PG-Strom 3.xはPostgreSQL 12以降をサポートしますが、今回PostgreSQLコミュニティのパッケージを入れます。

sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install postgresql-client-15 postgresql-15 postgresql-server-dev-15 libpq-dev

PG-Stromのインストール

間もなくPG-Strom 5.xがリリース予定ですが、今回はバージョン3.xをインストールしてみます。次のように実行してインストールしてください。

git clone -b v3.5 https://github.com/heterodb/pg-strom.git
cd pg-strom
make PG_CONFIG=/usr/bin/pg_config
sudo make install PG_CONFIG=/usr/bin/pg_config

ビルド後の設定

インストール後、次のような設定を行います。

Ubuntuの場合、PostgreSQLパッケージがインストールされた時点でinitdbは実行済みなので、設定の変更など行うだけです。

sudo su - postgres

テスト用ユーザーを作成

ログインするためのユーザーを作成します。パスワード入力を求められますので、このユーザーに対するパスワードを設定してください。

createuser -d -r -s -P mypguser

PostgreSQL設定の変更

PostgreSQLの設定に対して、PG-Strom共有ライブラリの設定とちょっとしたチューニングを施します。例記されている設定のうち、特に重要なのがshared_buffersです。実装しているメモリーの25%程度を設定するのが適切です。

cd /etc/postgresql/15/main/
vi postgresql.conf
...
#------------------------------------------------------------------------------
# CUSTOMIZED OPTIONS
#------------------------------------------------------------------------------

# Add settings for extensions here
shared_preload_libraries = '$libdir/pg_strom'
max_worker_processes = 100
shared_buffers = 4GB
work_mem = 1GB
listen_addresses = '*'

PostgreSQLの再起動

カスタマイズした設定を適用するためにサービス再起動します。

$ sudo systemctl restart postgresql@15-main.service

PostgreSQLにログイン

作ったユーザーでログインします。

$ psql -h 127.0.0.1 -U mypguser -d postgres

ユーザーを作ったときのパスワードを入力すると、ログインできます。

$ psql -h 127.0.0.1 -U mypguser -d postgres
Password for user mypguser: 
psql (15.3 (Ubuntu 15.3-1.pgdg20.04+1))
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.
postgres=#

次のように実行すると、現在接続中のDBでPG-Stromが使えます。

postgres=# CREATE EXTENSION pg_strom;

PG-Strom Quickstart

次のように実行してテストデータテーブルを作ってみてください。

postgres=# CREATE TABLE t_test1 AS
 SELECT       x, 'a'::char(100) AS y, 'b'::char(100) AS z
 FROM   generate_series(1, 5000000) AS x
 ORDER BY random();

次のように実行してみます。QUERY PLAN(実行計画)が表示されて、出力からGPUが使われていることがわかります。

EXPLAIN VERBOSE SELECT count(*)
 FROM   t_test1
 WHERE sqrt(x) > 0
 GROUP BY y;

                                                    QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
 GroupAggregate  (cost=100031.53..100031.55 rows=1 width=109)
   Output: pgstrom.sum((pgstrom.nrows())), y
   Group Key: t_test1.y
   ->  Sort  (cost=100031.53..100031.53 rows=2 width=109)
         Output: (pgstrom.nrows()), y
         Sort Key: t_test1.y
         ->  Gather  (cost=100031.31..100031.52 rows=2 width=109)
               Output: (pgstrom.nrows()), y
               Workers Planned: 2
               ->  Parallel Custom Scan (GpuPreAgg) on public.t_test1  (cost=99031.31..99031.32 rows=1 width=109)
                     Output: (pgstrom.nrows()), y
                     GPU Output: (pgstrom.nrows()), y
                     GPU Setup: '1'::bigint, y
                     Reduction: GroupBy (Global+Local [nrooms: 1974])
                     Group keys: t_test1.y
                     Outer Scan: public.t_test1  (cost=2833.33..98814.29 rows=694445 width=101)
                     Outer Scan Filter: (sqrt((t_test1.x)::double precision) > '0'::double precision)
                     GPU Preference: None
                     Kernel Source: /var/lib/postgresql/15/main/pgsql_tmp/pgsql_tmp_strom_8423.0.gpu
 JIT:
   Functions: 8
   Options: Inlining false, Optimization false, Expressions true, Deforming true
(22 rows)

次のように実行すると500万行のデータの検索が812ミリ秒、つまり1秒以下で終えられたことがわかります。速いですね。

postgres=# \timing
Timing is on.
postgres=# SELECT count(*)
 FROM   t_test1
 WHERE sqrt(x) > 0
 GROUP BY y;
  count  |
---------+-------------------
 5000000 | a
(1 row)

Time: 812.535 ms

これでPostgreSQLのクエリ実行にPG-StromでGPUを使って処理をスケールすることができるようになりました。 PG-Stromの利用ガイド などをみて、色々試してみてください。 Apache ArrowとかFluentd連携周りはなかなか面白いですよ。

より大規模なデータを取り扱うには商用ライセンスが必要ですが、それによりマルチGPUやGPUDirect Storageが利用できるようになり、100ギガバイトやテラバイトクラスのデータの処理を高速化できるようになります。

現在開発中のPG-Strom 5.xではロジックの改良を行っているとのことです。 まずは手元の環境でお試ししてみてください。