Skip to content

[GLUTEN-4421][VL] Disable flushable aggregate when input is already partitioned by grouping keys - #4443

Merged
zhztheplayer merged 9 commits into
apache:mainfrom
zhztheplayer:wip-fix-flush
Jan 19, 2024
Merged

[GLUTEN-4421][VL] Disable flushable aggregate when input is already partitioned by grouping keys#4443
zhztheplayer merged 9 commits into
apache:mainfrom
zhztheplayer:wip-fix-flush

Conversation

@zhztheplayer

@zhztheplayerzhztheplayer commented Jan 18, 2024

Copy link
Copy Markdown
Member

If child output already partitioned by aggregation keys (this function returns true), we should avoid the optimization converting to flushable aggregation.

For example, if input is hash-partitioned by keys (a, b) and aggregate node requests "group by a, b, c", then the aggregate should NOT flush as the grouping set (a, b, c) will be created only on a single partition among the whole cluster. Spark's planner may use this information to perform optimizations like doing "partial_count(a, b, c)" directly on the output data.

This fixes#4421

@zhztheplayer

Copy link
Copy Markdown
MemberAuthor

/Benchmark Velox

@github-actions

Copy link
Copy Markdown

#4421

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI

Comment thread.github/workflows/velox_be.yml Outdated
Comment on lines 172 to 181

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Later we may develop a new way to arrange these gluten-it CI jobs. The yaml file size is exploding.

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI

@zhztheplayer

Copy link
Copy Markdown
MemberAuthor

/Benchmark Velox

@zhztheplayer
zhztheplayer marked this pull request as ready for review January 18, 2024 08:55
@GlutenPerfBot

Copy link
Copy Markdown
Contributor

===== Performance report for TPCH SF2000 with Velox backend, for reference only ====

querylog/native_4443_time.csvlog/native_master_01_17_2024_6e070aee2_time.csvdifferencepercentage
q133.2132.53-0.67897.96%
q224.1425.151.012104.19%
q338.4035.63-2.76692.80%
q436.5139.472.965108.12%
q570.6469.91-0.72698.97%
q68.047.16-0.88089.06%
q784.8283.43-1.39798.35%
q884.8986.982.089102.46%
q9121.60125.573.971103.27%
q1044.7542.09-2.66394.05%
q1120.2720.23-0.04599.78%
q1224.9627.472.508110.05%
q1345.9844.85-1.13697.53%
q1420.9917.86-3.13485.07%
q1528.3029.771.468105.19%
q1614.1813.95-0.22998.39%
q17101.66100.92-0.73599.28%
q18148.63146.37-2.26598.48%
q1913.0213.910.897106.89%
q2026.5426.50-0.03699.87%
q21224.71226.251.543100.69%
q2213.5713.710.135101.00%
total1229.821229.72-0.10099.99%

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI

@zhztheplayer

Copy link
Copy Markdown
MemberAuthor

/Benchmark Velox

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI

@ulysses-you

Copy link
Copy Markdown
Contributor

I'm trying to understand this issue, please correct me if wrong. What we want to fix in this pr is: do not convert regular to flushable agg (2) because the flushable agg would output more than one group for the same group and then cause the partial count accumulator (3) bigger than expected.

SELECT c1, count(distinct c2), count(1) FROM t GROUP BY c1
(4) Aggregate [c1], [count(c2), count(1)]
Shuffle c1
(3) Aggregate [c1], [partial_count(c2), merge_count(1)]
(2) Aggregate [c1, c2], [merge_count(1)]
Shuffle c1, c2
(1) Aggregate [c1, c2], [partial_count(1)]

@GlutenPerfBot

Copy link
Copy Markdown
Contributor

===== Performance report for TPCH SF2000 with Velox backend, for reference only ====

querylog/native_4443_time.csvlog/native_master_01_18_2024_7c853c61f_time.csvdifferencepercentage
q133.2331.92-1.30996.06%
q223.6925.942.252109.50%
q334.7436.001.261103.63%
q438.3139.521.205103.14%
q566.6168.311.700102.55%
q66.995.33-1.65776.29%
q784.3083.20-1.10498.69%
q883.9884.620.638100.76%
q9122.96123.961.000100.81%
q1041.4842.821.336103.22%
q1119.9020.160.262101.32%
q1228.6626.88-1.78093.79%
q1345.6844.35-1.33097.09%
q1417.0016.22-0.77595.44%
q1528.4428.700.262100.92%
q1614.0713.92-0.14498.98%
q1798.7399.400.673100.68%
q18147.12145.71-1.40899.04%
q1912.5212.600.084100.67%
q2026.0026.330.326101.26%
q21223.06225.762.703101.21%
q2213.6413.59-0.05699.59%
total1211.101215.244.141100.34%

@zhztheplayer

Copy link
Copy Markdown
MemberAuthor

I'm trying to understand this issue, please correct me if wrong. What we want to fix in this pr is: do not convert regular to flushable agg (2) because the flushable agg would output more than one group for the same group and then cause the partial count accumulator (3) bigger than expected.

SELECT c1, count(distinct c2), count(1) FROM t GROUP BY c1
(4) Aggregate [c1], [count(c2), count(1)]
Shuffle c1
(3) Aggregate [c1], [partial_count(c2), merge_count(1)]
(2) Aggregate [c1, c2], [merge_count(1)]
Shuffle c1, c2
(1) Aggregate [c1, c2], [partial_count(1)]

It's more or less similar to the issue this PR is trying to solve. Except that Q38 generates plan like the following:

// Spark 3.3
(2) Aggregate [partial_count]
Shuffle ???
(1) Aggregate [c1, c2] // <- this should not be flushable
Shuffle c1, c2

In Spark 3.2 the agg (1) can be flushable since there was another distinct aggregation generated on reducer side:

// Spark 3.2
(2) Aggregate [partial_count]
(3) Aggregate [c1, c2]
Shuffle ???
(1) Aggregate [c1, c2] // <- this can be flushable
Shuffle c1, c2

That's why the issue is found starting from Spark 3.3. There might be some new optimizations from vanilla Spark.

@zhztheplayer

Copy link
Copy Markdown
MemberAuthor

I'm trying to understand this issue, please correct me if wrong. What we want to fix in this pr is: do not convert regular to flushable agg (2) because the flushable agg would output more than one group for the same group and then cause the partial count accumulator (3) bigger than expected.

SELECT c1, count(distinct c2), count(1) FROM t GROUP BY c1
(4) Aggregate [c1], [count(c2), count(1)]
Shuffle c1
(3) Aggregate [c1], [partial_count(c2), merge_count(1)]
(2) Aggregate [c1, c2], [merge_count(1)]
Shuffle c1, c2
(1) Aggregate [c1, c2], [partial_count(1)]

BTW, forgot to mention that current code should already be able to handle this case without this patch (we convert agg to flushable agg only when it's the one close to shuffle). But still thanks for taking the example which is valuable anyway.

@ulysses-you

Copy link
Copy Markdown
Contributor

The optimization since Spark3.3 is due to the pr apache/spark#35779. So we should not convert regular to flushable agg if it is a group by only aggreagate and it's adjacent parent is a partial aggregate ?

@zhztheplayer

Copy link
Copy Markdown
MemberAuthor

The optimization since Spark3.3 is due to the pr apache/spark#35779. So we should not convert regular to flushable agg if it is a group by only aggreagate and it's adjacent parent is a partial aggregate ?

Thanks for the information.

I think we indeed could forbid flushing on the case apache/spark#35779 optimizes against, although I am thinking whether the patch could provide a more general fix.

When an aggregate can be considered to emit distinct data and so propagate "distinct attributes", the distinct aggregation must be a "final distinct aggregation", which means it has to process data that are already partitioned by the distinct keys. Base on this assumption, the patch could be a correct fix (Correct me if I was wrong, indeed).

Additionally, the fix could be considered "general" since it's not limited to distinct aggregation. For example, a partial sum agg could produce meaningful data for a specific grouping set when it is handling input that was already partitioned by grouping keys. This may not be a good example since I doubt Catalyst planner never creates plan related to this case, but anyway the principle here is to be more careful to use flushable aggregation since vanilla Spark doesn't have this kind of optimization as of now.

@github-actions

Copy link
Copy Markdown

Run Gluten Clickhouse CI

@ulysses-you

Copy link
Copy Markdown
Contributor

This pr is a kind of conservative fix for the issue, that means it can fix the issue but may miss optimize some other cases, e.g., if the agg is on the top of a shuffled join with the same keys, then the partial agg would not be converted to flushable.

xxx
Shuffle
Aggregate xxx
Aggregate partial_xxx
Shuffled Join
Shuffle
Shuffle

I'm fine to fix it first since it's a data correctness issue, and do further optimization in next pr.

@zhztheplayer

Copy link
Copy Markdown
MemberAuthor

This pr is a kind of conservative fix for the issue, that means it can fix the issue but may miss optimize some other cases, e.g., if the agg is on the top of a shuffled join with the same keys, then the partial agg would not be converted to flushable.

xxx
Shuffle
Aggregate xxx
Aggregate partial_xxx
Shuffled Join
Shuffle
Shuffle

I'm fine to fix it first since it's a data correctness issue, and do further optimization in next pr.

I understand your point. And I think this kind of plan is not able to be optimized within flushable agg even without the patch. So let's keep enhancing the rule to cover more cases like that in further development iterations.

@ulysses-youulysses-you left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for the fix

@zhztheplayer
zhztheplayer merged commit d1e6ead into apache:mainJan 19, 2024
@zhztheplayer

Copy link
Copy Markdown
MemberAuthor

Thanks for reviewing!

@GlutenPerfBot

Copy link
Copy Markdown
Contributor

===== Performance report for TPCH SF2000 with Velox backend, for reference only ====

querylog/native_4443_time.csvlog/native_master_01_18_2024_7c853c61f_time.csvdifferencepercentage
q133.1631.92-1.23596.28%
q225.5325.940.409101.60%
q336.1636.00-0.15599.57%
q437.7739.521.749104.63%
q569.3468.31-1.03398.51%
q65.525.33-0.18696.64%
q784.2983.20-1.09498.70%
q884.8584.62-0.23399.73%
q9121.23123.962.728102.25%
q1042.2842.820.539101.28%
q1119.5820.160.581102.97%
q1227.0926.88-0.21899.19%
q1347.4144.35-3.05593.56%
q1416.3616.22-0.13799.16%
q1527.3828.701.318104.81%
q1613.1513.920.776105.90%
q1799.0399.400.369100.37%
q18147.03145.71-1.32099.10%
q1912.4912.600.112100.90%
q2026.6026.33-0.27598.97%
q21226.20225.76-0.44399.80%
q2213.7313.59-0.14398.96%
total1216.181215.24-0.94499.92%

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[VL] Flushable distinct agg caused correctness issue

3 participants

@zhztheplayer@GlutenPerfBot@ulysses-you