diff --git a/dnn/test/common/checker.cpp b/dnn/test/common/checker.cpp index ee39b65cf633b4437213a0ca9ad013d8df2cd230..8c5bbf90ad93886edb11875e3b1b106cc467fcc5 100644 --- a/dnn/test/common/checker.cpp +++ b/dnn/test/common/checker.cpp @@ -182,10 +182,10 @@ CheckerHelper::CheckerHelper(Handle *handle, bool check_dispatch): const char* env_p = std::getenv("MGB_NO_NAIVE_CHECK"); if (env_p) { int no_naive_flag = atoi(env_p); - no_naive_and_check = no_naive_flag > 0 ? true : false; + m_no_naive_and_check = no_naive_flag > 0 ? true : false; check_dispatch = false; } else { - no_naive_and_check = false; + m_no_naive_and_check = false; } auto tmp_handle = create_cpu_handle(2, check_dispatch); m_handle_naive = std::move(tmp_handle); @@ -282,7 +282,18 @@ void CheckerHelper::do_exec(const TensorLayoutArray &user_layouts, m_expect_exec_fail = {}; return; } - if (no_naive_and_check){ + if (m_stable_check) { + auto tensors_bak_host_storage = + alloc_tensors(m_handle_naive.get(), layouts, m_offset); + auto&& tensors_bak_host = *tensors_bak_host_storage; + copy_tensors_from_device(tensors_bak_host, tensors_cur); + for (int i = 0; i < 10; i++) { + exec_opr(tensors_cur); + copy_tensors_from_device(tensors_cur_host, tensors_cur); + check_tensors(tensors_bak_host, tensors_cur_host); + } + } + if (m_no_naive_and_check) { m_prev_succ = !::testing::Test::HasFailure(); return; } diff --git a/dnn/test/common/checker.h b/dnn/test/common/checker.h index e727cf622d67df313096b395055dc0f59b0fd32b..e7d6e0320d4075e05fac35e91e594baab71eb598 100644 --- a/dnn/test/common/checker.h +++ b/dnn/test/common/checker.h @@ -76,7 +76,8 @@ protected: ExtraOprImpl m_extra_opr_impl; OutputCanonizer m_output_canonizer; TensorsConstriant m_tensor_constraint; - bool no_naive_and_check = false; + bool m_no_naive_and_check = false; + bool m_stable_check = false; /** * the offset from the start of malloc memory * @@ -230,6 +231,17 @@ public: return *this; } + //! stable check will run many iter and compare result with first iter + Checker& set_stable_check(bool stable_check) { + m_stable_check = stable_check; + return *this; + } + + Checker& set_no_naive_check(bool no_naive_and_check) { + m_no_naive_and_check = no_naive_and_check; + return *this; + } + //! load input tensors from file for next run Checker& load_input_tensors(const char* fpath) { m_input_tensors_fpath = fpath; diff --git a/dnn/test/common/conv_bias.cpp b/dnn/test/common/conv_bias.cpp index 4a1a9605aa9c2f3ee07acc5852a82c8c80778ca5..b12e4f2e1955f52ec614f9926b59a248c619275e 100644 --- a/dnn/test/common/conv_bias.cpp +++ b/dnn/test/common/conv_bias.cpp @@ -731,9 +731,10 @@ std::vector get_int8_chwn4_tensorcore_args(size_t kernel_size) { void check_conv_bias(DType src_dtype, DType filter_dtype, DType bias_dtype, DType dst_dtype, Handle* handle, const char* algo, param::ConvBias::Format format, - const std::vector& args, bool fuse_z) { + const std::vector& args, bool fuse_z, + bool stable_test) { megdnn_assert(src_dtype.enumv() == filter_dtype.enumv()); - Checker checker(handle); + Checker checker(handle, !stable_test); if (algo) { checker.set_before_exec_callback( ConvBiasAlgoChecker(algo)); @@ -823,6 +824,10 @@ void check_conv_bias(DType src_dtype, DType filter_dtype, DType bias_dtype, .set_rng(1, rng.get()) .set_rng(2, bias_rng.get()) .set_rng(3, rng.get()); + if (stable_test) { + checker.set_stable_check(true); + checker.set_no_naive_check(true); + } if (args.empty()) { std::vector default_args; if (format == Format::NCHW4) { diff --git a/dnn/test/common/conv_bias.h b/dnn/test/common/conv_bias.h index b2b12d7337b741d698dfde30094091595a64a8d4..573efe64c2a0085924863951f063e0aef98a64d5 100644 --- a/dnn/test/common/conv_bias.h +++ b/dnn/test/common/conv_bias.h @@ -69,7 +69,7 @@ void check_conv_bias( DType src_dtype, DType filter_dtype, DType bias_dtype, DType dst_dtype, Handle* handle, const char* algo = nullptr, param::ConvBias::Format format = param::ConvBias::Format::NCHW4, - const std::vector& args = {}, bool fuse_z = false); + const std::vector& args = {}, bool fuse_z = false, bool stable_test = false); #if MEGDNN_WITH_BENCHMARK std::vector get_winograd_benchmark_args( diff --git a/dnn/test/common/warp_perspective.h b/dnn/test/common/warp_perspective.h index 3a094b353883ad86ce6055d01a498399f1d29231..3213ae5d5e4a61f01bf12258135c7f2c6c46472b 100644 --- a/dnn/test/common/warp_perspective.h +++ b/dnn/test/common/warp_perspective.h @@ -71,7 +71,7 @@ public: auto rand_real2 = [&](double range) { return rand_real(-range, range); }; - dt_float32 res; + dt_float32 res = 0; switch (idx) { case 0: rot = rand_real(0, M_PI * 2); diff --git a/dnn/test/cuda/utils.cpp b/dnn/test/cuda/utils.cpp index e04a0b7c2116ed5afc6257dfac62ed7a1a98ffb6..b1f529bd7e61d8df8a8dc61cc530bbacd8502a9b 100644 --- a/dnn/test/cuda/utils.cpp +++ b/dnn/test/cuda/utils.cpp @@ -28,6 +28,13 @@ bool check_compute_capability_eq(int major, int minor) { cuda_check(cudaGetDeviceProperties(&prop, dev)); return (prop.major == major && prop.minor == minor); } +const cudaDeviceProp current_cuda_device_prop() { + int dev; + cuda_check(cudaGetDevice(&dev)); + cudaDeviceProp prop; + cuda_check(cudaGetDeviceProperties(&prop, dev)); + return prop; +} } // namespace test } // namespace megdnn diff --git a/dnn/test/cuda/utils.h b/dnn/test/cuda/utils.h index 2484adbcbd6b9cf23611aa385ad5663591ac7d84..c0a9c94a0123ff119c7c37065930b005b6b16dbc 100644 --- a/dnn/test/cuda/utils.h +++ b/dnn/test/cuda/utils.h @@ -27,6 +27,7 @@ namespace megdnn { namespace test { bool check_compute_capability(int major, int minor); bool check_compute_capability_eq(int major, int minor); +const cudaDeviceProp current_cuda_device_prop(); } // namespace test } // namespace megdnn