onnx / onnx/optimizer

fuse_bn_into_conv optimization fails on big-endian architecture

Open
#6 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C++
Stars
834
Forks
109
Avg merge
6h 55m
Merged PRs (30d)
2

Description

Bug Report

This test was run on s390x. s390x is big-endian architecture.

Failure log from pytest:

_______________________________________________ TestOptimizer.test_fuse_bn_into_conv_simple ________________________________________________

self = <optimizer_test.TestOptimizer testMethod=test_fuse_bn_into_conv_simple>

    def test_fuse_bn_into_conv_simple(self):  # type: () -> None
        for (tensor_type, np_type) in [(TensorProto.FLOAT, np.float32), (TensorProto.DOUBLE, np.float64)]:
            conv = helper.make_node("Conv", ["X", "W", "B"], ["Y"])
            bn = helper.make_node("BatchNormalization", [
                                  "Y", "scale", "b", "mean", "var"], ["Z"])
    
            W = np.random.randn(3, 2, 5, 5).astype(np_type) + 2
            B = np.random.randn(3,).astype(np_type) + 2
            scale = np.random.randn(3,).astype(np_type) + 2
            b = np.random.randn(3,).astype(np_type) + 2
            mean = np.random.randn(3,).astype(np_type) + 2
            var = np.abs(np.random.randn(3,).astype(np_type)) + 2
    
            initializers = [
                helper.make_tensor(name, tensor_type,
                                   npa.shape, npa.tobytes(), raw=True)
                for name, npa in [('W', W), ('B', B), ('scale', scale), ('b', b), ('mean', mean), ('var', var)]
            ]
            graph = helper.make_graph(
                [conv, bn],
                "test",
                [helper.make_tensor_value_info("X", tensor_type, (5, 2, 28, 28)),
                 helper.make_tensor_value_info("W", tensor_type, (3, 2, 5, 5)),
                 helper.make_tensor_value_info("B", tensor_type, (3,)),
                 helper.make_tensor_value_info("scale", tensor_type, (3,)),
                 helper.make_tensor_value_info("b", tensor_type, (3,)),
                 helper.make_tensor_value_info("mean", tensor_type, (3,)),
                 helper.make_tensor_value_info("var", tensor_type, (3,))],
                [helper.make_tensor_value_info(
                    "Z", tensor_type, (5, 3, 24, 24))],
                initializer=initializers,
                value_info=[
                    helper.make_tensor_value_info(
                        "Y", tensor_type, (5, 3, 24, 24))
                ]
            )
            optimized_model = self._optimized(graph, ["fuse_bn_into_conv"])
    
            self.assertEqual(len(optimized_model.graph.node), 1)
            self.assertEqual(optimized_model.graph.node[0].op_type, 'Conv')
            self.assertEqual(len(optimized_model.graph.initializer), 2)
            new_W = numpy_helper.to_array(optimized_model.graph.initializer[0])
            new_b = numpy_helper.to_array(optimized_model.graph.initializer[1])
    
            f = scale / np.sqrt(var + 1e-5)
>           np.testing.assert_almost_equal((B - mean) * f + b, new_b)
E           AssertionError: 
E           Arrays are not almost equal to 7 decimals
E           
E           Mismatched elements: 3 / 3 (100%)
E           Max absolute difference: 2.7824624e+14
E           Max relative difference: 1.0692023e+32
E            x: array([-1.3619891,  2.4206262,  2.2576501], dtype=float32)
E            y: array([-4.7447069e-14, -2.2639551e-32,  2.7824624e+14], dtype=float32)

optimizer_test.py:1509: AssertionError

The fuse_bn_into_conv.h code does not account for potentially running on a big-endian architecture machine when running the optimization routines.

Attached is a patch file with updated source files with a proposed fix for this optimization issue.

onnx-opt.patch.zip

A pull request can be submitted if needed.

Contributor guide

No contributing guide indexed for this repository

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 fuse_bn_into_conv.h and optimizer_test.py::TestOptimizer::test_fuse_bn_into_conv_simple, then review the attached onnx-opt.patch.zip for the proposed direction. Run the focused pytest on a big-endian s390x environment and verify that the fused model has one Conv node, two initializers, and matching bias values.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
performance
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.