From 00dfe61b8390b0c1158942f6c762efcc22850ffc Mon Sep 17 00:00:00 2001 From: Yaman Umuroglu <maltanar@gmail.com> Date: Wed, 13 May 2020 14:55:51 +0100 Subject: [PATCH] [Transform] bugfix in MoveReshape, rename to RemoveCNVtoFCFlatten --- notebooks/end2end_example/cnv_end2end_example.ipynb | 6 +++--- src/finn/transformation/move_reshape.py | 4 ++-- tests/end2end/test_end2end_cnv_w1a1.py | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/notebooks/end2end_example/cnv_end2end_example.ipynb b/notebooks/end2end_example/cnv_end2end_example.ipynb index f4bff38ce..ce8c9decf 100644 --- a/notebooks/end2end_example/cnv_end2end_example.ipynb +++ b/notebooks/end2end_example/cnv_end2end_example.ipynb @@ -274,7 +274,7 @@ "from finn.transformation.fpgadataflow.create_dataflow_partition import (\n", " CreateDataflowPartition,\n", ")\n", - "from finn.transformation.move_reshape import MoveReshape\n", + "from finn.transformation.move_reshape import RemoveCNVtoFCFlatten\n", "from finn.custom_op.registry import getCustomOp\n", "\n", "# choose the memory mode for the MVTU units, decoupled or const\n", @@ -286,7 +286,7 @@ "model = model.transform(to_hls.InferConvInpGen())\n", "model = model.transform(to_hls.InferStreamingMaxPool())\n", "# get rid of Reshape(-1, 1) operation between hlslib nodes\n", - "model = model.transform(MoveReshape())\n", + "model = model.transform(RemoveCNVtoFCFlatten())\n", "parent_model = model.transform(CreateDataflowPartition())\n", "parent_model.save(build_dir + \"/end2end_cnv_w1a1_dataflow_parent.onnx\")\n", "sdp_node = parent_model.get_nodes_by_op_type(\"StreamingDataflowPartition\")[0]\n", @@ -301,7 +301,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Notice the additional `MoveReshape` transformation that was not used for TFC-w1a1. In the last Netron visualization you may have noticed a `Reshape` operation towards the end of the network where the convolutional part of the network ends and the fully-connected layers started. That `Reshape` is essentialy a tensor flattening operation, which we can remove for the purposes of hardware implementation. We can examine the contents of the dataflow partition with Netron, and observe the `ConvolutionInputGenerator`, `StreamingFCLayer_Batch` and `StreamingMaxPool_Batch` nodes that implement the sliding window, matrix multiply and maxpool operations in hlslib. *Note that the StreamingFCLayer instances following the ConvolutionInputGenerator nodes are really implementing the convolutions, despite the name. The final three StreamingFCLayer instances implement actual FC layers.*" + "Notice the additional `RemoveCNVtoFCFlatten` transformation that was not used for TFC-w1a1. In the last Netron visualization you may have noticed a `Reshape` operation towards the end of the network where the convolutional part of the network ends and the fully-connected layers started. That `Reshape` is essentialy a tensor flattening operation, which we can remove for the purposes of hardware implementation. We can examine the contents of the dataflow partition with Netron, and observe the `ConvolutionInputGenerator`, `StreamingFCLayer_Batch` and `StreamingMaxPool_Batch` nodes that implement the sliding window, matrix multiply and maxpool operations in hlslib. *Note that the StreamingFCLayer instances following the ConvolutionInputGenerator nodes are really implementing the convolutions, despite the name. The final three StreamingFCLayer instances implement actual FC layers.*" ] }, { diff --git a/src/finn/transformation/move_reshape.py b/src/finn/transformation/move_reshape.py index 6a30fd93c..2ddaf4f84 100644 --- a/src/finn/transformation/move_reshape.py +++ b/src/finn/transformation/move_reshape.py @@ -17,7 +17,7 @@ def _is_fpgadataflow_node(node): return False -class MoveReshape(Transformation): +class RemoveCNVtoFCFlatten(Transformation): """Removes a node that implements a (1, -1) reshape if it is between two fpgadataflow nodes""" @@ -27,13 +27,13 @@ class MoveReshape(Transformation): graph_modified = False for n in graph.node: if n.op_type == "Reshape": - graph_modified = True shape = model.get_initializer(n.input[1]) if (shape == [1, -1]).all(): producer = model.find_producer(n.input[0]) if _is_fpgadataflow_node(producer) is True: consumer = model.find_consumer(n.output[0]) if _is_fpgadataflow_node(consumer) is True: + graph_modified = True consumer.input[0] = n.input[0] graph.node.remove(n) diff --git a/tests/end2end/test_end2end_cnv_w1a1.py b/tests/end2end/test_end2end_cnv_w1a1.py index d7f59ef35..703cb7ad9 100644 --- a/tests/end2end/test_end2end_cnv_w1a1.py +++ b/tests/end2end/test_end2end_cnv_w1a1.py @@ -41,7 +41,7 @@ from finn.custom_op.registry import getCustomOp from finn.core.onnx_exec import execute_onnx from finn.transformation.double_to_single_float import DoubleToSingleFloat from finn.transformation.infer_shapes import InferShapes -from finn.transformation.move_reshape import MoveReshape +from finn.transformation.move_reshape import RemoveCNVtoFCFlatten from finn.transformation.fold_constants import FoldConstants from finn.transformation.general import GiveReadableTensorNames, GiveUniqueNodeNames from finn.transformation.streamline import Streamline @@ -117,7 +117,7 @@ def test_end2end_cnv_w1a1_convert_to_hls_layers(): model = model.transform(to_hls.InferQuantizedStreamingFCLayer(mem_mode)) model = model.transform(to_hls.InferConvInpGen()) model = model.transform(to_hls.InferStreamingMaxPool()) - model = model.transform(MoveReshape()) + model = model.transform(RemoveCNVtoFCFlatten()) model.save(build_dir + "/end2end_cnv_w1a1_hls_layers.onnx") -- GitLab