Skip to content

Investigate custom Triton kernels for depthwise-separable convolutions in Conformer #2733

Open

Description

@asumagic

Describe the bug

A decent chunk of time in the Conformer model at training time is spent in the convolution module. Of that, a decent chunk is in the depthwise convolution, which sets groups to the input size. Suspiciously much, if anything.

On ROCm, at least on my 7900XT, it appeared that streaming: True shredded performance and ~doubles training time (which i didn't observe on CUDA), so I tried giving optimizing it a shot.
I didn't observe improvements from using torch.compile, even with max-autotune.
I tried AMD's Composable Kernels and the relevant torch.compile backend, but I will decline elaborating on my experience getting it working lest this become an unhinged rant at the ROCm ecosystem.

So, I wrote up a prototype using Triton (OpenAI's compiler, not the inference server) with no prior experience for a forward pass, reusing realistic shapes:

image

This prompted an instant massive WTF. I am not 100% sure my benchmark is correct (I reused Triton's tutorials'), but I couldn't find anything wrong and the output tensors matched.
Even more strangely, similar performance benefits could be observed on A100.

So, this issue will track my progress on trying to apply this in practice. Currently only doing this on my free time.

Expected behaviour

speed

To Reproduce

No response

Environment Details

No response

Relevant Log Output

No response

Additional Context

No response

Activity

  1. added
    enhancementNew feature or request
    performanceIssue or fix for something slow or memory-hungry
    on Oct 27, 2024
  2. asumagic commented on Oct 27, 2024

    @asumagic
    CollaboratorAuthor

    Noting that I wrote this kernel to process the input tensor in a (batch, steps, channels) format.
    In comparison, PyTorch kernels use a (batch, channels, steps) format. It remains a fair comparison, since there is no way around this. PyTorch has some support for NWHC, but only for Conv2D.

    In both cases, the native representation was fed and thus no permutation affects the benchmark.

    The performance differential might originate from this (maybe? not sure) and the existing kernels not being specialized enough? Haven't looked into PyTorch/CuDNN to understand why.

  3. asumagic commented on Oct 30, 2024

    @asumagic
    CollaboratorAuthor

    I spent a bit more time on this recently in my spare time and implemented the backward pass. It is probably not fully correct yet, especially when Dynamic Chunk Convolutions are involved (getting gradcheck failures and not quite sure how to resolve them yet).

    I observed (very) significant performance gains on ROCm, especially with DCC, but a degradation on Nvidia (and an A100 definitely shouldn't be slower than my 7900XT).

    I didn't try to inspect performance further, but it might have to do with the way I implemented the for loop over the kernel size that might be way suboptimal. Will have to check if trying to remove away that loop to express it as a single load and dot product would work.

    I also hacked a dirty proof of concept to add it to a Conformer RNN-T model. It helped training speed a fair bit, and didn't fully break the model (although I didn't let it run nearly long enough to check if WER was correct).
    Another potential candidate would be the downsampling CNN with Fast Conformer (which replaces some Conv2D by a depthwise-separable convolution), which is also super slow on ROCm, but that requires implementing stride.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestperformanceIssue or fix for something slow or memory-hungry

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions