-
Notifications
You must be signed in to change notification settings - Fork 79
Fine grained compute transform #970
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
base: main
Are you sure you want to change the base?
Changes from all commits
375066c
745f841
8896644
6230e11
80839ba
c1ba35b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,120 @@ | ||
| import islpy as isl | ||
| import namedisl as nisl | ||
|
|
||
| import loopy as lp | ||
| from loopy.kernel import LoopKernel | ||
| from loopy.kernel.data import AddressSpace | ||
| from loopy.kernel.instruction import MultiAssignmentBase | ||
| from loopy.match import parse_stack_match | ||
| from loopy.symbolic import ( | ||
| RuleAwareSubstitutionMapper, | ||
| SubstitutionRuleMappingContext, | ||
| pw_aff_to_expr | ||
| ) | ||
| from loopy.transform.precompute import contains_a_subst_rule_invocation | ||
| from loopy.translation_unit import for_each_kernel | ||
|
|
||
| from pymbolic import var | ||
| from pymbolic.mapper.substitutor import make_subst_func | ||
|
|
||
| from pytools.tag import Tag | ||
|
|
||
|
|
||
| @for_each_kernel | ||
| def compute( | ||
| kernel: LoopKernel, | ||
| substitution: str, | ||
| compute_map: isl.Map | nisl.Map, | ||
| storage_inames: list[str], | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed this the first time around.
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Prefer |
||
| default_tag: Tag | str | None = None, | ||
| temporary_address_space: AddressSpace | None = None | ||
| ) -> LoopKernel: | ||
| """ | ||
| Inserts an instruction to compute an expression given by :arg:`substitution` | ||
| and replaces all invocations of :arg:`substitution` with the result of the | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not really: only the relevant ones, where relevant should be defined below. |
||
| compute instruction. | ||
|
|
||
| :arg substitution: The substitution rule for which the compute | ||
| transform should be applied. | ||
|
|
||
| :arg compute_map: An :class:`isl.Map` representing a relation between | ||
| substitution rule indices and tuples `(a, l)`, where `a` is a vector of | ||
| storage indices and `l` is a vector of "timestamps". | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How is the boundary of
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In it's current form, it relies on user input to determine what |
||
| """ | ||
| if isinstance(compute_map, isl.Map): | ||
| compute_map = nisl.make_map(compute_map) | ||
|
|
||
| if not temporary_address_space: | ||
| temporary_address_space = AddressSpace.GLOBAL | ||
|
|
||
| # {{{ normalize names | ||
|
|
||
| iname_to_storage_map = { | ||
| iname : (iname + "_store" if iname in kernel.all_inames() else iname) | ||
| for iname in storage_inames | ||
| } | ||
|
|
||
| compute_map = compute_map.rename_dims(iname_to_storage_map) | ||
|
|
||
| # }}} | ||
|
|
||
| # {{{ update kernel domain to contain storage inames | ||
|
|
||
| new_storage_axes = list(iname_to_storage_map.values()) | ||
|
|
||
| # FIXME: use DomainChanger to add domain to kernel | ||
| storage_domain = compute_map.range().project_out_except(new_storage_axes) | ||
| new_domain = kernel.domains[0] | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use the |
||
|
|
||
| # }}} | ||
|
|
||
| # {{{ express substitution inputs as pw affs of (storage, time) names | ||
|
|
||
| compute_pw_aff = compute_map.reverse().as_pw_multi_aff() | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this particular instance, it expresses substitution inputs as piecewise affine functions of |
||
|
|
||
| storage_ax_to_global_expr = { | ||
| dim_name : pw_aff_to_expr(compute_pw_aff.get_at(dim_name)) | ||
| for dim_name in compute_map.dim_type_names(isl.dim_type.in_) | ||
| } | ||
|
|
||
| # }}} | ||
|
|
||
| # {{{ generate instruction from compute map | ||
|
|
||
| rule_mapping_ctx = SubstitutionRuleMappingContext( | ||
| kernel.substitutions, kernel.get_var_name_generator()) | ||
|
|
||
| expr_subst_map = RuleAwareSubstitutionMapper( | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You'll need to subclass this guy. Otherwise you won't be able to decide whether the usage site is "in-footprint".
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding was that Do you mean |
||
| rule_mapping_ctx, | ||
| make_subst_func(storage_ax_to_global_expr), | ||
| within=parse_stack_match(None) | ||
| ) | ||
|
|
||
| subst_expr = kernel.substitutions[substitution].expression | ||
| compute_expression = expr_subst_map(subst_expr, kernel, None) | ||
|
Check failure on line 94 in loopy/transform/compute.py
|
||
|
|
||
| temporary_name = substitution + "_temp" | ||
| assignee = var(temporary_name)[tuple( | ||
| var(iname) for iname in new_storage_axes | ||
| )] | ||
|
|
||
| compute_insn_id = substitution + "_compute" | ||
| compute_insn = lp.Assignment( | ||
| id=compute_insn_id, | ||
| assignee=assignee, | ||
| expression=compute_expression, | ||
| ) | ||
|
|
||
| # }}} | ||
|
|
||
| # {{{ replace substitution rule with newly created instruction | ||
|
|
||
| for insn in kernel.instructions: | ||
| if contains_a_subst_rule_invocation(kernel, insn) \ | ||
| and isinstance(insn, MultiAssignmentBase): | ||
| print(insn) | ||
|
|
||
|
|
||
| # }}} | ||
|
|
||
| return kernel | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems this could just be a
@for_each_kerneldecorator?