NVIDIA / NVIDIA/TensorRT

Performance Regression: PTQ-INT8 Quantization for nn.Conv2d with parameter groups > 1 is Slower than FP16

Open
#4,529 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Module:Performance Module:Quantization triaged
Dominant language
C++
Stars
13.4k
Forks
2.4k
Avg merge
5d 3h
Merged PRs (30d)
2

Description

Description
I am encountering a significant performance regression when performing Post-Training Quantization (PTQ) on a PyTorch nn.Conv2d layer where the groups parameter is greater than 1. Specifically, after converting such models to a TensorRT engine with INT8 quantization, the inference speed becomes noticeably slower than its FP16 counterpart.

Upon analyzing the generated TensorRT computation graph (using tools like trex or polygraphy's dump features), it appears that when groups > 1, TensorRT is not optimizing the grouped convolution as a single fused operation for quantization. Instead, it seems to be splitting the grouped convolution into individual, separate convolution operations for each group, and then quantizing each of these smaller, disaggregated convolutions. This disaggregation, particularly in the context of INT8 quantization, seems to introduce overhead that leads to the observed performance degradation, making the INT8 engine perform worse than the FP16 engine.

This behavior is unexpected, as INT8 quantization is generally intended to improve performance.

As an example of the issue described above, my model consists of three convolutional layers in series, with the second convolutional layer being the one exhibiting the problem (where groups > 1). I have also provided the model code and the SVG computation graph exported using trex below for visualization.

mode code:

`
model = nn.Sequential(
# the first conv layer:3->in_channels, stride=2
nn.Conv2d(
in_channels=in_channels,
out_channels=in_channels,
kernel_size=3,
stride=2,
padding=1,
groups=1,
bias=True # 使用bias
),

    # the second conv layer:in_channels->out_channels, stride=2
    nn.Conv2d(
        in_channels=in_channels,
        out_channels=out_channels,
        kernel_size=3,
        stride=2,
        padding=1,
        groups=groups,
        bias=True  # 使用bias
    ),
    
    # the third conv layer:out_channels->128, kernel_size=1
    nn.Conv2d(
        in_channels=out_channels,
        out_channels=128,
        kernel_size=1,
        stride=1,
        padding=0,
        groups=1,
        bias=True  # 使用bias
    ),
).cuda()

`

SVG view:

Image

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the three-layer nn.Conv2d example in the issue and reproduce the INT8 versus FP16 performance difference. Inspect the generated computation graph with trex or Polygraphy's dump features, focusing on how the grouped convolution is decomposed. Done means identifying the cause of the grouped-convolution regression and verifying a corrective result against the provided model.

Written by the indexing model from the issue text.

Assessment

Tech stack
python, pytorch
Domain
machine-learning, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.