NVIDIA / NVIDIA/TensorRT

[stable-diffusion v2] ONNX pattern matching for mhca and mha plugins is not working

Open
#2,539 11 comments 0 reactions 1 assignee View on GitHub

@nekorobov is already working on this.

Since Dec 9, 2022.

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

Description

Description

The pattern matching used in the diffusion demo for replacing memory head attention with the optimized plugins is not working with stable diffusion v2 in the demo-diffusion.

Resulting to this TensorRT error :

[E] 10: [optimizer.cpp::computeCosts::3712] Error Code 10: Internal Error (Could not find any implementation for node {ForeignNode[MatMul_450...MatMul_457]}.)
[E] 2: [builder.cpp::buildSerializedNetwork::738] Error Code 2: Internal Error (Assertion engine != nullptr failed. )
[!] Invalid Engine. Please ensure the engine was built correctly.

I would like to know if it is something easily patchable on my side in the function mha_mhca_detected from demo-diffusion

Environment

TensorRT branch release/8.5
Docker container image : nvcr.io/nvidia/tensorrt:22.10-py3

Relevant Files

Files models.py and demo_diffusion.py with stable-diffusion-2 support are in the files.zip archive
After investigation, the graphs are not identical. For example, the projection layers in v1 use Conv instead of Linear in v2.

With fhma plugin support deactivated, we can observe that the ONNX graphs are not the same between the two version.
An additional MatMul operation is added as input for the attention part. I suspect this additional operator being responsible of the issue.

Subgraph-v1, Attention Input:
subgraph-v1

Subgraph-v2, Attention Input:
subgraph-v2

Also, I am not sure where this part should applied in the graph :

    def mha_mhca_detected(self, node, mha):
        # Go from V GEMM down to the S*V MatMul and all way up to K GEMM
        # If we are looking for MHCA inputs of two matmuls (K and V) must be equal.
        # If we are looking for MHA inputs (K and V) must be not equal.
        if node.op == "MatMul" and len(node.outputs) == 1 and \
            ((mha and len(node.inputs[0].inputs) > 0  and node.i().op == "Add") or \
            (not mha and len(node.inputs[0].inputs) == 0)):

            dynamic_batch = (node.o().op == 'Shape')
            o = node.o(1) if dynamic_batch else node.o()
            if o.op == "Reshape" and \
                o.o().op == "Transpose" and \
                o.o().o().op == "Reshape" and \
                o.o().o().o().op == "MatMul" and \
                o.o().o().o().i(0).op == "Softmax" and \
                o.o().o().o().i(1).op == "Reshape" and \
                o.o().o().o().i(0).i().op == "Mul" and \
                o.o().o().o().i(0).i().i().op == "MatMul" and \
                o.o().o().o().i(0).i().i().i(0).op == "Reshape" and \
                o.o().o().o().i(0).i().i().i(1).op == "Transpose" and \
                o.o().o().o().i(0).i().i().i(1).i().op == "Reshape" and \
                o.o().o().o().i(0).i().i().i(1).i().i().op == "Transpose" and \
                o.o().o().o().i(0).i().i().i(1).i().i().i().op == "Reshape" and \
                o.o().o().o().i(0).i().i().i(1).i().i().i().i().op == "MatMul" and \
                node.name != o.o().o().o().i(0).i().i().i(1).i().i().i().i().name:
                # "len(node.outputs) == 1" to make sure we are not in the already fused node
                node_q = o.o().o().o().i(0).i().i().i(0).i().i().i()
                node_k = o.o().o().o().i(0).i().i().i(1).i().i().i().i()
                node_v = node
                final_tranpose = o.o().o().o().o(1).o() if dynamic_batch else o.o().o().o().o().o()
                # Sanity check to make sure that the graph looks like expected
                if node_q.op == "MatMul" and final_tranpose.op == "Transpose":
                    return True, dynamic_batch, node_q, node_k, node_v, final_tranpose
        return False, False, None, None, None, None

If you have additional information to explain this pattern matching, it could be great.

Steps To Reproduce

pip3 install -r demo/Diffusion/requirements.txt
Follow the steps from hugging face : https://huggingface.co/stabil
ityai/stable-diffusion-2
pip3 install --upgrade git+https://github.com/huggingface/diffusers.git transformers accelerate scipy
Run the demo:
LD_PRELOAD=${PLUGIN_LIBS} python3 demo/Diffusion/demo-diffusion.py "" -v

files.zip

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.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.