caseの条件式でdivision by zeroを回避出来ない。
Closed this issue · 4 comments
0-kaz commented
CASE文でid % 71の結果が0になる場合を回避しているが、以下SQLでdivizion by zeroが発生する。
SELECT id, CASE id % 71
WHEN 0 THEN -1.0
ELSE 1 / (id % 71)
END v3
FROM regtest_data
WHERE id > 0;
エラーメッセージ
ERROR: xpu_basetype.cu:683 int4div: division by zero
HINT: device at GPU-0, function at pgfn_int4div
全体クエリ
DROP TABLE IF EXISTS regtest_data;
CREATE TABLE regtest_data (
id int,
a numeric
);
SELECT pgstrom.random_setseed(20190701);
INSERT INTO regtest_data (
SELECT x, pgstrom.random_float(20,-100.0,100.0)::numeric(9,3)
FROM generate_series(1,6000) x
);
SET enable_seqscan = off;
SET pg_strom.enabled = on;
SELECT id, CASE id % 71
WHEN 0 THEN -1.0
ELSE 1 / (id % 71)::real
END v3
FROM regtest_data
WHERE id > 0;
0-kaz commented
以下のSQLは期待通り動作しますので、CASE <計算式> WHEN <値> ~の構文を処理する箇所で起きている可能性が高そうです。
SELECT id, CASE WHEN id % 71 = 0 THEN -1.0
ELSE 1 / (id % 71)
END v3
FROM regtest_data
WHERE id > 0;
kaigai commented
これ、CASE ... WHEN 文全体をGPUで処理するのではなく、その一部だけを別個に処理するという判断をしている(サポートされていない演算子か?)ので、1 / (id % 71)::real
をGPU Kernelから返していますね。
あんまインテリジェンスを働かさずに、全体をGPU実行できない場合は大人しくCPU実行にした方がいいかなぁ…。
hoge=# explain SELECT id, CASE id % 71
WHEN 0 THEN -1.0
ELSE 1 / (id % 71)::real
END v3
FROM regtest_data
WHERE id > 0;
QUERY PLAN
---------------------------------------------------------------------------------------------------------
Custom Scan (GpuScan) on regtest_data (cost=100.00..267.92 rows=5999 width=12)
GPU Projection: id, (id % 71), 0, '-1'::double precision, ('1'::double precision / ((id % 71))::real)
GPU Scan Quals: (id > 0) [rows: 6000 -> 5999]
GPU-Direct SQL: enabled (GPU-0)
(4 rows)
kaigai commented
72a8faa0324407a7ea3d02bca01107acfe44a15b
と 0d0c3e7c596fc7e2e8ac4bf7c2c4e00cd4338ebb
にて修正しています。2つの問題がありました。
まず、CASE WHEN ... な構文の際に出てくる CaseTestExpr
のハンドリングに誤りがあった事。
もう一つは、GPUでの実行に対応していない構文が与えられた時に、GPUで計算できる部分だけでも計算するようにしていた事で、親切な事に 1 / (id % 71)::real
もGPUで計算してこれをホストに返そうとしていたようでした。
0-kaz commented
確認しました。ご対応ありがとうございました。