pytorch - 💡(How to fix) Fix Why does register_replacement not support fuzzy matching for optional parameters in operators when using search_fn or search_fn_pattern? [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
pytorch/pytorch#177822Fetched 2026-04-08 01:01:39
View on GitHub
Comments
2
Participants
2
Timeline
38
Reactions
0
Author
Timeline (top)
mentioned ×16subscribed ×16commented ×2renamed ×2

Code Example

npu_quant_matmul(x1, x2, scale, *, offset=None, pertoken_scale=None, bias=None) -> Tensor

---

# Only matches Case 1
def search_fn(x1, x2, scale, offset, bias):
    trans = x2.transpose(0, 1)
    return torch.ops.npu.npu_quant_matmul.default(x1, trans, scale, offset=offset, bias=bias)

# Only matches Case 2
def search_fn(x1, x2, scale):
    trans = x2.transpose(0, 1)
    return torch.ops.npu.npu_quant_matmul.default(x1, trans, scale)

---

def _build_search_pattern():
        npu_transpose_func = CallFunction(
            torch.ops.aten.transpose.int, 
            KeywordArg("x2"), 
            Ignored(), 
            Ignored(), 
            _users=1
        )

        output = CallFunction(
            torch.ops.npu.npu_quant_matmul.default, 
            KeywordArg("x1"),
            npu_transpose_func,
            KeywordArg('scale'),
            offset=KeywordArg('offset'), #Alternatively, writing Ignore() here will cause a failure during the matching process when verifying that len(self.args)!=len(node.args)
            bias=KeywordArg('bias'), 
            _users=1
        )

        return output
RAW_BUFFERClick to expand / collapse

I am attempting to write a pattern matcher to match fused operators, and currently encounter an issue: neither search_fn nor search_fn_pattern provides a way to perform fuzzy matching for optional parameters. For example, optional parameters like offset and bias in the following operator prototype appear differently in the FX graph when they are passed or omitted:

Operator prototype as follows:

npu_quant_matmul(x1, x2, scale, *, offset=None, pertoken_scale=None, bias=None) -> Tensor

Case 1 (with optional parameters): torch.ops.npu.npu_quant_matmul.default(arg2_1, arg3_1, arg4_1, offset=arg5_1, bias=arg6_1); Case 2 (without optional parameters): torch.ops.npu.npu_quant_matmul.default(arg2_1, arg3_1, arg4_1); Attempt 1: Using search_fn The following search_fn only matches Case 1 and fails to match Case 2 (where optional parameters are omitted). To cover Case 2, I have to write a separate search_fn:

# Only matches Case 1
def search_fn(x1, x2, scale, offset, bias):
    trans = x2.transpose(0, 1)
    return torch.ops.npu.npu_quant_matmul.default(x1, trans, scale, offset=offset, bias=bias)

# Only matches Case 2
def search_fn(x1, x2, scale):
    trans = x2.transpose(0, 1)
    return torch.ops.npu.npu_quant_matmul.default(x1, trans, scale)

Attempt 2: Using search_fn_pattern (CallFunction) I also tried using search_fn_pattern (from torch._inductor.pattern_matcher import register_replacement as register) and wrote a CallFunction as shown below. However, using Ignored() results in a placeholder *, which causes a failure during the matching process when verifying len(self.args)!=len(node.args). It seems impossible to match both cases with a single CallFunction:

def _build_search_pattern():
        npu_transpose_func = CallFunction(
            torch.ops.aten.transpose.int, 
            KeywordArg("x2"), 
            Ignored(), 
            Ignored(), 
            _users=1
        )

        output = CallFunction(
            torch.ops.npu.npu_quant_matmul.default, 
            KeywordArg("x1"),
            npu_transpose_func,
            KeywordArg('scale'),
            offset=KeywordArg('offset'), #Alternatively, writing Ignore() here will cause a failure during the matching process when verifying that len(self.args)!=len(node.args)
            bias=KeywordArg('bias'), 
            _users=1
        )

        return output

Impact: Some operators may have more optional parameters (e.g., n optional parameters). In such cases, I would need to write 2ⁿ search_fn or search_fn_pattern to cover all scenarios, which is extremely inefficient and unscalable. Questions:

  1. Is there any syntax to perform fuzzy matching for this scenario, so that both cases (with/without optional parameters passed) can be matched with a single pattern?
  2. What is the difference between the two writing methods in the matching process: 1.CallFunction(offset=KeywordArg('offset')) 2.CallFunction(KeywordArg('offset'))?

cc @chauhang @penguinwu @voznesenskym @EikanWang @jgong5 @Guobing-Chen @XiaobingSuper @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @kadeng @amjames @Lucaskabela @jataylo @mlazos

extent analysis

Fix Plan

To address the issue of fuzzy matching for optional parameters, we can utilize the Optional class from the torch._inductor.pattern_matcher module. This allows us to define a pattern that can match both cases where optional parameters are present or absent.

Here's an example of how you can modify your search_fn_pattern to achieve this:

from torch._inductor.pattern_matcher import Optional

def _build_search_pattern():
    npu_transpose_func = CallFunction(
        torch.ops.aten.transpose.int, 
        KeywordArg("x2"), 
        Ignored(), 
        Ignored(), 
        _users=1
    )

    output = CallFunction(
        torch.ops.npu.npu_quant_matmul.default, 
        KeywordArg("x1"),
        npu_transpose_func,
        KeywordArg('scale'),
        Optional(KeywordArg('offset')), 
        Optional(KeywordArg('bias')), 
        _users=1
    )

    return output

In this modified version, Optional(KeywordArg('offset')) and Optional(KeywordArg('bias')) allow the pattern to match whether the offset and bias parameters are provided or not.

Verification

To verify that this fix works, you can test your pattern matching function with both cases (where optional parameters are present and where they are absent) and ensure that it correctly matches and replaces the target patterns.

Extra Tips

  • The Optional class is specifically designed for handling optional parameters in pattern matching, making it a more elegant and scalable solution than writing multiple patterns for each combination of optional parameters.
  • When using CallFunction, the difference between offset=KeywordArg('offset') and KeywordArg('offset') lies in how the argument is passed to the function. The former specifies the keyword argument explicitly, which is necessary when the argument name in the function definition does not match the variable name in your pattern. The latter is used when the argument is positional or when its name matches the variable name in your pattern. However, in the context of Optional, using KeywordArg directly is more appropriate as it clearly defines the parameter's name and its optional nature.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING