Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refine GpuHashAggregateExec.setupReference #2917

Merged
merged 6 commits into from
Jul 16, 2021

Conversation

sperlingxx
Copy link
Collaborator

@sperlingxx sperlingxx commented Jul 13, 2021

Signed-off-by: sperlingxx [email protected]

Current PR refined GpuHashAggregateExec.setupReference to support TypedImperativeAggregate, which is required by #2916 . The primary work of current PR is reorganizing the code of boundInputReferences.

Originally, we workaround PartialMerge modes when we construct boundInputReferences. To be specific, the code piece dealing with aggregations which contain both PartialMerge and Partial mode is not generic enough. It regards GpuPivotFirst and GpuAverage as exceptional cases:

      case Partial =>
        // Partial with distinct case
        val updateExpressionsCudfAggsDistinct =
          updateExpressionsDistinct.filter(_.isInstanceOf[CudfAggregate])
              .map(_.asInstanceOf[CudfAggregate].ref)
        if (inputProjectionsDistinct.exists(p => !p.isInstanceOf[NamedExpression])) {
          // Case of distinct average we need to evaluate the "GpuCast and GpuIsNotNull" columns.
          // Refer to how input projections are setup for GpuAverage.
          // In the case where we have expressions to evaluate, pick the unique attributes
          // references from them as you only have one column for it before you start evaluating.
          distinctExpressions = inputProjectionsDistinct
          distinctAttributes = inputProjectionsDistinct.flatMap(ref =>
            ref.references.toSeq).distinct
        } else {
          distinctAttributes = updateAttributesDistinct
          distinctExpressions = updateExpressionsCudfAggsDistinct
        }

With the new implementation, we avoid all kinds of workaround. Instead, we fit all kinds of aggregation modes into three categories by the stage of AggregateExec in aggregation stack:

  1. The first stage of aggregation stack, in terms of aggregation modes, it may contain aggregate expressions with Partial or Complete mode. It may also contain no aggregate expressions. For the first aggregation stage, the input projections are necessary, because it consume the outputs of non-Aggregate plans.

  2. The final-like stages, including three conditions:

    • the final (last) stage of aggregation stack
    • the (partial) merge stage merely for nonDistinctAggAttributes (the second stage of aggregation stack with one distinct)

    For final-like stages, we just pass through all output attributes of child plan.

  3. The third stage of aggregation stack with one distinct, in terms of aggregation modes, it contains both Partial mode (for distinctAgg) and PartialMerge mode (for nonDistinctAgg). For this stage, we need to switch the position of distinctAttributes and nonDistinctAttributes to match the output schema of the previous stage:

    • the schema of the 2nd stage's outputs: groupingAttributes ++ distinctAttributes ++ nonDistinctAggBufferAttributes
    • the schema of the 3rd stage's aggregate expressions: nonDistinctMergeAggExpressions ++ distinctPartialAggExpressions

@sperlingxx sperlingxx added feature request New feature or request task Work required that improves the product but is not user facing and removed feature request New feature or request labels Jul 13, 2021
@sperlingxx
Copy link
Collaborator Author

build

@abellina
Copy link
Collaborator

Could you add to the description for this PR around what exactly was changed and why? Please also note this PR is in flight: #2859, and also makes changes to setupReferences.

Signed-off-by: sperlingxx <[email protected]>
Signed-off-by: sperlingxx <[email protected]>
@sperlingxx
Copy link
Collaborator Author

build

@sperlingxx
Copy link
Collaborator Author

Could you add to the description for this PR around what exactly was changed and why? Please also note this PR is in flight: #2859, and also makes changes to setupReferences.

I added the description. And I rebased this branch onto latest main branch.

Signed-off-by: sperlingxx <[email protected]>
@sperlingxx
Copy link
Collaborator Author

build

@revans2
Copy link
Collaborator

revans2 commented Jul 14, 2021

@abellina and @jlowe could both of you take a look at this? You have a lot more experience with the aggregate code than I do. It looks okay to me, but I don't feel 100% qualified to approve it.

@abellina
Copy link
Collaborator

@revans2 yeap, I am looking.

Copy link
Collaborator

@abellina abellina left a comment

Choose a reason for hiding this comment

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

Thanks for the added details @sperlingxx. I am mostly curious on the update expressions, as we used to use them before in the PartialMerge + Partial case https://github.com/NVIDIA/spark-rapids/blob/branch-21.08/sql-plugin/src/main/scala/com/nvidia/spark/rapids/aggregate.scala#L679. I think the comments need to be adjusted but it would be nice to make sure that you found that input projections is all that is needed in that case (perhaps the shapes match?)

Tagging @kuhushukla and @nartal1 as they may be more familiar with both distinct and pivot.

Had other minor nits.

// Pick merge non-distinct for PartialMerge
val mergeExpressionsNonDistinct =
nonDistinctAggExpressions
// - PartialMerge with Partial mode: we use the inputProjections or distinct update expressions
Copy link
Collaborator

Choose a reason for hiding this comment

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

Comments mention distinct update expressions, but I am not finding the use of update expressions in your change, only input projections.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I updated this part along with comments, in order to verify and clarify "input projections is all that is needed in that case".

// - Final or PartialMerge-only mode: we pick the columns in the order as handed to us.
// - Partial or Complete mode: we use the inputProjections or distinct update expressions.
val boundInputReferences =
if (modeInfo.hasPartialMerge && modeInfo.uniqueModes.contains(Partial)) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
if (modeInfo.hasPartialMerge && modeInfo.uniqueModes.contains(Partial)) {
if (modeInfo.hasPartialMerge && modeInfo.hasPartialMode) {

Copy link
Collaborator

Choose a reason for hiding this comment

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

bonus points => hasPartialMerge => hasPartialMergeMode

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We used modeInfo.uniqueModes.contains(Partial) instead of modeInfo.hasPartialMode here, because hasPartialMode is set as hasPartialMerge || uniqueModes.contains(Partial). I adjusted AggregateModeInfo to make its members more consistent with their names.

Signed-off-by: sperlingxx <[email protected]>
@sperlingxx
Copy link
Collaborator Author

build

abellina
abellina previously approved these changes Jul 15, 2021
Copy link
Collaborator

@abellina abellina left a comment

Choose a reason for hiding this comment

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

I had a couple of nits, but they are minor. Approving ahead of time. Thanks for making the tweaks.

@sperlingxx
Copy link
Collaborator Author

build

@sperlingxx sperlingxx requested a review from abellina July 16, 2021 01:19
Copy link
Collaborator

@abellina abellina left a comment

Choose a reason for hiding this comment

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

LGTM

@sperlingxx sperlingxx merged commit 25197b8 into NVIDIA:branch-21.08 Jul 16, 2021
@sperlingxx sperlingxx deleted the rework_setup_ref branch July 16, 2021 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
task Work required that improves the product but is not user facing
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants