しかつきかふぇ

ちょっとした休憩時間に

GPU で PostgreSQL を高速化する PG-Strom をやってみた!

青ブタ映画公開中!

鹿野です。
昨日は現在構築中のサーバー用にHDDを買いにアキバまで行ってきたのですが、一番の収穫はHDDよりもこっちのカレンダーだったりして。

今公開中の映画は先週観に行きましたが、その話もしたいけど余裕ないのでまたできたときにその話はしますね。

さて、その話は今度こそ置いといて、今日は openSUSE Advent Calendar 2023 の 17日目の記事です。
今日のネタは PostgreSQLGPU で高速化しよう!みたいなお話です。
オープンソースカンファレンス日本仮想化技術 さんがデモをしているアレですね。

event.ospn.jp ※日本openSUSEユーザ会は次回1月の OSC大阪2024 に出展します。

ざっくりと手順!

元ネタ記事は酒井さんの下記のブログです。OSC新潟ではお世話になりました!

sakaik.hateblo.jp

今回は openSUSE Leap 15.5 で動作確認を行っています。
PostgreSQL のバージョンも 15.5 です。たまたま番号が一緒なだけですがね!!
ですが感触としては恐らく Tumbleweed でも同じ手順で行けると思います。(躓くとしたらCUDAのインストールくらいか。いつものことだけど)

  1. CUDA 11.7 のインストール
  2. PostgreSQL 関連パッケージのインストール
  3. PG-Strom のビルド
  4. PostgreSQL の設定と再起動
  5. PG-Strom をロードして実行

注意点としては、 PG-Strom の v3 系の場合、 CUDA 12系では動かないということです。 ※12/20追記 少なくとも 12.1 ではビルド中にコアダンプはいてコケました!!
とりあえず PyTorch 2.0 が動く CUDA 11.7 で試したところ、こちらではビルドが通ったので、恐らく CUDA 11系で動くということだと思われます。厳密にはちゃんと確認してませんが、ひとまず CUDA 11.7 付近のもので試してみてください。

CUDA 11.7 のインストール

現在インストールされている CUDA のバージョンで PG-Strom のビルドが通れば本手順は不要ですが、まだ CUDA が未インストール、あるいは以下に紹介する手順で PG-Strom のビルドが通らない場合は、いつもどおり(?)こちらの記事を参考にしてください。

cafe.shikanotsuki.me

ただ、 11.7 だとやや古くて使いにくいかもしれませんので、 下記のように update-alternatives でバージョンを切り替えられうようにしておくといいと思います。

sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-11.7 1
sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-12.1 2

CUDA のバージョン書き換えはこんな具合ですね。

> sudo update-alternatives --config cuda

There are 2 choices for the alternative cuda (providing /usr/local/cuda).

  Selection    Path                   Priority   Status
------------------------------------------------------------
  0            /usr/local/cuda-12.1/   2         auto mode
* 1            /usr/local/cuda-11.7/   1         manual mode
  2            /usr/local/cuda-12.1/   2         manual mode

Press <enter> to keep the current choice[*], or type selection number: 1

つまり PG-Strom を使用する場合は CUDA 11.7 になるわけですね・・・
(こういうときのために Docker が使えればいいのだけど、、openSUSENVIDIA-Docker は相性が悪いんですよね)

PostgreSQL 関連パッケージのインストール

PG-Strom を動かすのに必要なパッケージは下記のとおりです

  • postgresql
  • postgresql-server-devel ※PG-Stromのビルドに必要
  • libicu-devel ※PG-Stromのビルドに必要
  • postgresql15-postgis ※公式にはパッケージなし

注意が必要なのは、 postgresql15-postgis は公式リポジトリに存在していませんでした。
ただ、OBS(動画のアレじゃなくてビルドする方)上には存在しているので、それを使うことができます。

https://software.opensuse.org/package/postgresql15-postgis

openSUSE Leap 15.5 であれば『実験的なパッケージの表示』をクリックすると、 Application:Geo で開発されているものが表示されます。こちらを1クリックインストールすれば解決できます。

というわけでビルドの準備ができました。

PG-Strom のビルド

ソースコードは下記から git clone してきます。

github.com

git clone git@github.com:heterodb/pg-strom.git

# ビルド
cd pg-strom/src
make

# インストール
sudo make install

何も考えずにマスターブランチのものをビルドしてしまいましたが、CUDA 11.7 なら数分とかからずあっという間にビルドが完了します。
てか、昨日 v5.0 がリリースされたばかりだったんですね。(何が変わったのかは未確認です)
※(12/20追記)v5.0 の場合は CUDA 12.2 以降が必要となるようです。ご注意ください。

PostgreSQL の設定と再起動

インストールも終わったので、 PostgreSQL で早速試してみよう!
・・・と行きたいところですが、もうちょい手順が必要が必要です。

酒井さんの記事にもありますが、この手順を忘れるとフツーにこの後コケます!! うん、私もめっちゃハマった!!! (もうちょいわかりやすいところに書いておいてほしかったw)

sudo vi /var/lib/pgsql/data/postgresql.conf

shared_preload_libraries という文字列を検索して、下記のように書き換えてください。
設定値に関しては酒井さんのブログ記事そのままを記載してます。

shared_preload_libraries = '$libdir/pg_strom'

shared_buffers = 128MB               # min 128kB (とりあえずデフォルトまま変更しなかった)
max_worker_processes = 100      # for PG-Strom
work_mem = 1GB                         # for PG-Strom

修正したら、PostgreSQL の再起動も忘れずに。

sudo systemctl restart postgresql

PG-Strom をロードして実行

それでは早速動かしてみます。
・・・なのだけど、私が PostgreSQL の超初心者なの忘れてました(笑)
PostgreSQL の初期設定についてはもう少しスマートな方法があると思うので、ここで紹介する手順はあくまで参考までにお願いします。

まずは PostgreSQL クライアントである psql を起動・・・するために、postgres ユーザーになります。

sudo su - postgres
psql -c "alter user postgres with password 'PASSWORD'"

続けて psql へ入ります。

psql

データベースを作成して、接続してみます。

postgres=# CREATE DATABASE pgstest;
postgres=# \c pgstest;

ここでエクステンションとして、 PG-Strom と PostGIS を有効化します。

pgstest=# CREATE EXTENSION postgis;
pgstest=# CREATE EXTENSION pg_strom;

・・・・・。

まさかと思いますが、下記のエラーは出ていませんよね? (私は最初出たけどw)

pgstest=# CREATE EXTENSION pg_strom;
ERROR:  PG-Strom must be loaded via shared_preload_libraries

このエラーが出た方は、上の文章に戻って postgresql.conf を設定し直してください。

pgstest=# CREATE EXTENSION pg_strom;
CREATE EXTENSION

エラーが出ずにこんな感じに表示されればとりあえず準備完了です。

試してみよう!!

マニュアルはこちらにあります。

PG-Strom Manual

今回は酒井さんの記事に習って、下記のようにテーブルを作成してみます。

CREATE TABLE points1000man (gid int primary key, x float8, y float8, category int);

INSERT INTO points1000man (
  SELECT x, 
         pgstrom.random_float(0, 128.0, 146.5),
         pgstrom.random_float(0, 28.0,  45.6),
         pgstrom.random_int(0, 1,20 )
    FROM generate_series(1,10000000) x);

で、同様に下記のクエリを試そうと思ったのだけど、、、

SELECT ST_Distance(ST_MakePoint(137.0, 44.0), ST_MakePoint(x,y)) FROM points1000man
    WHERE ST_Distance(ST_MakePoint(137.0, 44.0), ST_MakePoint(x,y))<0.5;

なぜかエラーが出る。。。(なんで〜!??←このあたり PostgreSQL 超初心者であることが露呈。)

pgstest=# SELECT ST_Distance(ST_MakePoint(137.0, 44.0), ST_MakePoint(x,y)) FROM points1000man
pgstest-#     WHERE ST_Distance(ST_MakePoint(137.0, 44.0), ST_MakePoint(x,y))<0.5;
ERROR:  unknown alignment

なので、こんなふうに試してみた。

pgstest=# explain SELECT *  FROM points1000man where category=12;
                                      QUERY PLAN                                      
--------------------------------------------------------------------------------------
 Custom Scan (GpuScan) on points1000man  (cost=100.00..80475.75 rows=528327 width=24)
   GPU Projection: gid, x, y, category
   GPU Scan Quals: (category = 12) [rows: 9999884 -> 528327]
(3 行)

とりあえず GPU が使用されてることがわかります。(ぉぃ

速度も確認してみましょう。 ・・・ここでこの記事のオチがわかった方は天才かもしれない!!

pgstest=# \timing
タイミングは on です。

pgstest=# SELECT count(*)  FROM points1000man where category=12;
 count  
--------
 525614
(1 行)

時間: 470.727 ミリ秒

続けて、GPUなしでの速度も測ってみます。・・・うん、今度こそオチもわかったのでは?

pgstest=# SET pg_strom.enabled=false;
SET
時間: 0.573 ミリ秒

pgstest=# SELECT count(*)  FROM points1000man where category=12;
 count  
--------
 525614
(1 行)

時間: 191.630 ミリ秒

はい。CPUの方が速いことがわかりました!!(おいこら

と、GPUがどんな代物であるか想像できれば想定内の結果で、恐らく演算の発生しないタスクであればCPUの方が速いような気がします。CPUメモリとGPUメモリとで転送が発生するためですね。数を数えるだけのタスクであればメモリ転送が発生しない分、CPUの方が速そうです。

ではなくて、酒井さんの記事のように、SELECT文内に演算タスクが含まれている場合(特に乗算処理)に、GPUの方が速くなるのではと。

まとめ

私のSQL知識不足でまともに検証らしいことができていないのですが、基本的には GPU を使用した検索が速くなることが多いと思います。

個人的に気になったのは、これを深層学習の学習に使えないかなって点ですね。
CUDA のバージョンをうまく合わせられれば、うまく活用できるのではないでしょうか。

P.S.
てゆか霧島透子ってひょっとしてまさかと思うけどア○○○○○ミ???
※原作でもまだちゃんと描かれてないし、ネタバレにもなるのでこれ以上は書きません!!