You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tvm.apache.org by ma...@apache.org on 2023/04/05 19:13:54 UTC

[tvm] branch main updated: [Test][Topi] Avoid depending on f32 rounding behavior for crop_and_divide tests (#13773)

This is an automated email from the ASF dual-hosted git repository.

masahi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new 6caf08589b [Test][Topi] Avoid depending on f32 rounding behavior for crop_and_divide tests (#13773)
6caf08589b is described below

commit 6caf08589b169697eb8ed4a470044cc18bd3c44e
Author: Eric Lunderberg <Lu...@users.noreply.github.com>
AuthorDate: Wed Apr 5 14:13:46 2023 -0500

    [Test][Topi] Avoid depending on f32 rounding behavior for crop_and_divide tests (#13773)
    
    * [Test][Topi] Use binary fractions for crop_and_divide unit tests
    
    The `crop_and_resize` operator uses floating-point arithmetic to
    determine whether an index is within a view-box.  This can cause the
    use of `extrapolation_value` to depend on target-dependent rounding
    differences.
    
    For example, this issue was initially noticed on Vulkan during
    debugging of https://github.com/apache/tvm/pull/13530, and was the
    result of computing `0.2*223.0 + 0.8*223.0 < 223.0`.  If all
    intermediates are cast to float32, the left-hand side evaluates to
    `223.00002`.  If intermediates are kept at a higher precision, the
    left-hand side evaluates to `223.0`.
    
    The floating-point indexing can't be removed, because the operator
    must match the API defined by TensorFlow's operator implementation.
    The TensorFlow documentation for
    [`CropAndResize`](https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/crop-and-resize)
    does not specify behavior in these cases, nor do the current
    TensorFlow unit tests check cases of rounding error.  Since the
    TensorFlow unit tests only use binary fractions for the `boxes`
    argument, which largely avoids the rounding issue, this commit updates
    the TVM unit tests to avoid depending on floating-point precision.
    
    * Use seeded random data for unit test
    
    * Add epsilon offset to avoid depending on floating-point behavior
    
    * Use randomly-generated boxes for unit tests
    
    This mimics the example usage of `tf.image.crop_and_resize`, whose API
    this operator is intended to follow.  Using any boxes with edges
    representable as integer fractions has the potential for the in-bounds
    check to be impacted by rounding error (e.g. `0.2*x + 0.8*x < x`).
    Unfortunately, there's no way to remove this possibility altogether
    without changing the API, such as accepting the box location as an
    integer fraction, rather than a `float32`, but that would break
    compatibility.
    
    To avoid the risk of a flaky unit test based on the specific random
    boxes used, the PRNG is seeded prior to generation.
---
 tests/python/relay/test_op_level5.py | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/tests/python/relay/test_op_level5.py b/tests/python/relay/test_op_level5.py
index 10d0ea0d6d..db910661ca 100644
--- a/tests/python/relay/test_op_level5.py
+++ b/tests/python/relay/test_op_level5.py
@@ -236,14 +236,18 @@ class TestCropAndResize:
 
         extrapolation_value = 0.0
 
+        np.random.seed(0)
+
+        eps = 1e-4
+
         if layout == "NHWC":
             img_shape = (10, 224, 224, 3)
-            boxes = np.array([[0.1, 0.2, 0.8, 0.7], [0.2, 0, 1, 0.6]]).astype("float32")
+            boxes = np.random.uniform(size=(2, 4)).astype("float32")
             box_indices = np.array([1, 0]).astype("int32")
             crop_size = np.array([20, 30]).astype("int32")
         elif layout == "NCHW":
             img_shape = (5, 3, 255, 255)
-            boxes = np.array([[0, 0, 1, 1], [0.2, 0.1, 1, 0.9]]).astype("float32")
+            boxes = np.random.uniform(size=(2, 4)).astype("float32")
             box_indices = np.array([0, 1]).astype("int32")
             crop_size = np.array([30, 30]).astype("int32")
         else: