Xilinx / finn

Dataflow compiler for QNN inference on FPGAs
https://xilinx.github.io/finn
BSD 3-Clause "New" or "Revised" License
723 stars 230 forks source link

IndexError when lower_convs_to_matmul on #908

Closed ChristiaanBoe closed 11 months ago

ChristiaanBoe commented 11 months ago

Hello everyone I have been trying to implement a simple 3-layer neural network consisting of a quantlinear, a fully connected layer and a 1 dimensional 1-d convolutional layer as shown below: ONNX files.zip

class QuantfullModel_alt(nn.Module):
    def __init__(self, input_size,  bit_width = 8):
        super(QuantfullModel_alt, self).__init__()
        self.input_size = input_size
        self.bit_width = bit_width
        self.quantizer = qnn.QuantIdentity(act_quant=Int8ActPerTensorFloat, return_quant_tensor=True)
        self.quantfftlayer= qnn.QuantLinear(input_size, (input_size * 2),  bias=False, weight_bit_width=self.bit_width,  return_quant_tensor= True)
        self.quantifftlayer= qnn.QuantConv1d( self.input_size,(self.input_size*2), 1, bias=False, weight_bit_width=self.bit_width, return_quant_tensor= True, bias_quant=BiasQuant)

    def forward(self, x):
        x = self.quantizer(x)
        x = self.quantfftlayer(x)
        x = x.view(1, -1,1)
        x = self.quantifftlayer(x)

        return x

I converted this towards a qonnx model and then using the qonnx_cleanup and the ConvertQONNXtoFINN towards a finn model as shown n the code below and in the attached onnx files. export_qonnx(fullModel_alt, torch.randn(1, 1024), export_path='Test_all_alt.onnx')


# clean-up
qonnx_cleanup('FFT_test_all_alt.onnx', out_file='Test_clean.onnx')

# ModelWrapper
model = ModelWrapper('Test_clean.onnx')
model = model.transform(ConvertQONNXtoFINN())
model.save('Test_final.onnx')

When running this through the automated buildataflow I get the following error on lower_convs_to_matmul.py

    k_w = k[1]
IndexError: list index (1) out of range

> /home/local/brevtest/finn/deps/qonnx/src/qonnx/transformation/lower_convs_to_matmul.py(77)apply()
     75                 k = get_by_name(n.attribute, "kernel_shape").ints
     76                 k_h = k[0]
---> 77                 k_w = k[1]
     78                 stride_h = get_by_name(n.attribute, "strides").ints[0]
     79                 stride_w = get_by_name(n.attribute, "strides").ints[1]

ipdb>  q

Build failed
CPU times: user 18min 4s, sys: 5min 53s, total: 23min 57s
Wall time: 2d 19h 1min 37s

Using the following code:

import finn.builder.build_dataflow as build
import finn.builder.build_dataflow_config as build_cfg
import os
import shutil

model_dir = os.environ['FINN_ROOT'] + "/notebooks/end2end_example/Test"
model_file = model_dir + "/test_final.onnx"
final_output_dir = "output_final"

#Delete previous run results if exist
if os.path.exists(final_output_dir):
    shutil.rmtree(final_output_dir)
    print("Previous run results deleted!")

cfg = build.DataflowBuildConfig(
    output_dir          = final_output_dir,
    mvau_wwidth_max     = 80,
    target_fps          = 1000000,
    synth_clk_period_ns = 10.0,
    board               = "Pynq-Z1",
    shell_flow_type     = build_cfg.ShellFlowType.VIVADO_ZYNQ,
    generate_outputs=[
        build_cfg.DataflowOutputType.BITFILE,
        build_cfg.DataflowOutputType.PYNQ_DRIVER,
        build_cfg.DataflowOutputType.DEPLOYMENT_PACKAGE,
    ]
)

What could the problem be with my model?

The first thing that comes to mind is that my convolutional layer has a kernel twice the size as the output channel.

Thank you in advance for the help

auphelia commented 11 months ago

Hi @ChristiaanBoe ,

FINN works on 4D tensors (N,C,H,W) or later in the flow (N,H,W,C), so when working with 1d convolutions, you need to add a dummy dimension to get it through the flow: https://github.com/fastmachinelearning/qonnx/blob/main/src/qonnx/transformation/change_3d_tensors_to_4d.py