heterodb / pg-strom

PG-Strom - Master development repository
http://heterodb.github.io/pg-strom/
Other
1.3k stars 162 forks source link

Wrong CPU-Fallback in GiST-Join with large geometries #812

Closed sakaik closed 1 week ago

sakaik commented 4 months ago

ST_Crosses()関数を使用したクエリを実行したところ、PG-Stromがクラッシュしました。

Query

SELECT m.key_code , m.shape FROM chiri_mesh m, shinsui_geom s
 WHERE m.key_code like '533925%' 
   AND ST_crosses(m.shape, s.g)=True
 ORDER BY key_code ;

クラッシュ時の画面出力内容

db=# SELECT m.key_code , m.shape FROM chiri_mesh m, shinsui_geom s
 WHERE m.key_code like '533925%' 
   AND ST_crosses(m.shape, s.g)=True
 ORDER BY key_code ;
NOTICE:  GpuJoin: CPU fallback 102098 tuples (68.15MB)
WARNING:  terminating connection because of crash of another server process
DETAIL:  The postmaster has commanded this server process to roll back the current transaction and exit, because another server process exited abnormally and possibly corrupted shared memory.
HINT:  In a moment you should be able to reconnect to the database and repeat your command.
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Failed.
The connection to the server was lost. Attempting reset: Failed.
!?> 

backtrace

(gdb) bt
#0  0x00000000006a013d in CheckVarSlotCompatibility.isra.11.part.12 ()
#1  0x00000000006a0765 in CheckExprStillValid ()
#2  0x00000000006a0786 in ExecInterpExprStillValid ()
#3  0x00007f5ae8c53ccb in ExecEvalExprSwitchContext (isNull=0x7ffd8f376d42, econtext=0x1cdca68, state=<optimized out>)
    at /usr/pgsql-16/include/server/executor/executor.h:355
#4  ExecQual (econtext=0x1cdca68, state=<optimized out>) at /usr/pgsql-16/include/server/executor/executor.h:424
#5  __execFallbackCpuNestLoop (matched=false, l_state=1, depth=1, oj_map=0x0, kds_in=<optimized out>, pts=0x1cdc660)
    at fallback.c:267
#6  __execFallbackCpuJoinOneDepth (pts=pts@entry=0x1cdc660, depth=1, l_state=l_state@entry=1, matched=matched@entry=false)
    at fallback.c:454
#7  0x00007f5ae8c54279 in execCpuFallbackOneTuple (pts=pts@entry=0x1cdc660, depth=<optimized out>, l_state=1, 
    matched=<optimized out>) at fallback.c:490
#8  0x00007f5ae8c54569 in execCpuFallbackOneChunk (pts=pts@entry=0x1cdc660) at fallback.c:565
#9  0x00007f5ae8c4fffe in tryExecCpuFallbackChunks (pts=0x1cdc660) at executor.c:1105
#10 pgstromExecScanAccess (pts=0x1cdc660) at executor.c:1713
#11 0x00007f5ae8c51ce6 in pgstromExecScanAccess (pts=0x1cdc660) at executor.c:1689
#12 pgstromExecTaskState (node=0x1cdc660) at executor.c:1915
#13 0x00000000006d8f6e in ExecSort ()
#14 0x00000000006a87e3 in standard_ExecutorRun ()
#15 0x00000000006aca56 in ParallelQueryMain ()
#16 0x000000000058bf3c in ParallelWorkerMain ()
#17 0x00000000007b7fed in StartBackgroundWorker ()
#18 0x00000000007bd343 in maybe_start_bgworkers ()
#19 0x00000000007bdbbf in ServerLoop ()
#20 0x00000000007c018d in PostmasterMain ()
#21 0x00000000005073cf in main ()
(gdb) 

Version

db=# select pgstrom.githash();
                 githash                  
------------------------------------------
 ee77f34b2934b30cdd5b7dcd3a643bacbcbb3c5c
(1 row)

実行計画

EXPLAIN ANALYZEはクラッシュするので、参考になるか分かりませんが EXPLAINの結果:

db=# explain SELECT m.key_code , m.shape FROM chiri_mesh m, shinsui_geom s
 WHERE m.key_code like '533925%' 
   AND ST_crosses(m.shape, s.g)=True
 ORDER BY key_code ;
                                                    QUERY PLAN                                                    
------------------------------------------------------------------------------------------------------------------
 Gather Merge  (cost=85615617.89..85679365.97 rows=546374 width=130)
   Workers Planned: 2
   ->  Sort  (cost=85614617.86..85615300.83 rows=273187 width=130)
         Sort Key: m.key_code
         ->  Parallel Custom Scan (GpuJoin) on shinsui_geom s  (cost=19696.44..85589949.72 rows=273187 width=130)
               GPU Projection: m.key_code, m.shape
               GPU Join Quals [1]: st_crosses(m.shape, s.g) ... [nrows: 3125975 -> 273187]
               GPU-Direct SQL: enabled (GPU-0)
               ->  Parallel Custom Scan (GpuScan) on chiri_mesh m  (cost=100.00..19593.59 rows=84 width=130)
                     GPU Projection: key_code, shape
                     GPU Scan Quals: ((key_code)::text ~~ '533925%'::text) [rows: 2006036 -> 84]
                     GPU-Direct SQL: enabled (GPU-0)
(12 rows)
sakaik commented 2 weeks ago

本件、da05771daa205b684b2eb30ee5a7dbfb1ddde20e でも確認してみたところ、 クラッシュはしなくなったのですが、超時間(30分以上) NOTICE: GpuJoin: CPU fallback 0 tuples (0B) が何度も出続ける(7秒に1回くらい)事象となりました。(不具合でfallbackがループし続けているのか、順調に処理が進行しる=時間が掛かっているだけ=状態なのかは検証していません)

参考:実行計画変わりました

db=# explain SELECT m.key_code , m.shape FROM chiri_mesh m, shinsui_geom s
 WHERE m.key_code like '533925%' 
   AND ST_crosses(m.shape, s.g)=True
 ORDER BY key_code ;
                                                  QUERY PLAN                                                   
---------------------------------------------------------------------------------------------------------------
 Gather Merge  (cost=727416.75..890148.24 rows=1394744 width=130)
   Workers Planned: 2
   ->  Sort  (cost=726416.73..728160.16 rows=697372 width=130)
         Sort Key: m.key_code
         ->  Parallel Custom Scan (GpuJoin) on chiri_mesh m  (cost=623710.41..658731.30 rows=697372 width=130)
               GPU Projection: m.key_code, m.shape
               GPU Scan Quals: ((m.key_code)::text ~~ '533925%'::text) [rows: 2006141 -> 84]
               GPU Join Quals [1]: st_crosses(m.shape, s.g) ... [nrows: 84 -> 697372]
               GPU GiST Join [1]: (s.g && m.shape) on idx_gst_shinsui (g)
               GPU-Direct SQL: enabled (N=1,GPU0-0)
               ->  Parallel Seq Scan on shinsui_geom s  (cost=0.00..520805.47 rows=3120547 width=1030)

なお、このときの key_codeでの chiri_mesh絞り込み結果は400件です。

db=# SELECT COUNT(*) FROM chiri_mesh WHERE key_code like '533925%';
 count 
-------
   400
kaigai commented 2 weeks ago

こちら、chiri_mesh.shape に外部参照が必要な可変長データがいくつも含まれているといった具合でしょうか。 ただ、それにしても CPU-Fallback が 0B というのは妙ですね。

Slackの方でアクセス情報を教えてもらえないでしょうか。

kaigai commented 1 week ago

いくつかの問題が複合的に絡み合った問題でした。 ①st_crosses()がCPU-Fallbackを発生させるのは、再帰呼び出しに伴うGPUスタックの不足 ⇒スタック領域のサイズ設定のロジックを見直し。 ②GiST-JOIN時にCPU-Fallbackバッファへの書き込み処理が適切に行われていない ⇒CPU-Fallbackするように ③st_crosses()で本来 false を返すべき Polygon - Polygon の比較が、未定義値を返していた ⇒きちんとfalseを返すよう修正

sakaik commented 1 week ago

現時点の最新版 3c6814440b9fc678c58fece0a49383dd83b52630 にて、エラーや永久的なループが発生しなくなることを確認しました。

今回のテストデータでは結果ゼロ件を得ましたが、これは ST_Crosses()がPolygonどうしの交叉をTrueとは判定しないためなので(そういうデータでした)、正常動作するようになったと判断します。