Make MVN behaviour deterministic (#2458)

* Change default parallel reduce alg into deternimistic way

Signed-off-by: Alexander Peskov <alexander.peskov@intel.com>

* Introduce ie::parallel_for semantic with group_id parameter

Signed-off-by: Alexander Peskov <alexander.peskov@intel.com>

* [CPU] Make MVN behaviour deterministic

Signed-off-by: Alexander Peskov <alexander.peskov@intel.com>
This commit is contained in:
Alexander Peskov 2020-10-26 21:01:38 +03:00 committed by GitHub
parent 40a4ae3cfa
commit 6e5a4714ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 12 deletions

View File

@ -15,6 +15,7 @@
#pragma once
#include <cstddef>
#include <type_traits>
#define IE_THREAD_TBB 0
#define IE_THREAD_OMP 1
@ -185,7 +186,7 @@ void parallel_sort(I begin, I end, const F& comparator) {
template <typename T0, typename R, typename F>
R parallel_sum(const T0& D0, const R& input, const F& func) {
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
return tbb::parallel_reduce(
return tbb::parallel_deterministic_reduce(
tbb::blocked_range<T0>(0, D0), input,
[&](const tbb::blocked_range<T0>& r, R init) -> R {
R sum = init;
@ -217,7 +218,7 @@ R parallel_sum(const T0& D0, const R& input, const F& func) {
template <typename T0, typename T1, typename R, typename F>
R parallel_sum2d(const T0& D0, const T1& D1, const R& input, const F& func) {
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
return tbb::parallel_reduce(
return tbb::parallel_deterministic_reduce(
tbb::blocked_range2d<T0, T1>(0, D0, 0, D1), input,
[&](const tbb::blocked_range2d<T0, T1>& r, R init) -> R {
R sum = init;
@ -256,7 +257,7 @@ R parallel_sum2d(const T0& D0, const T1& D1, const R& input, const F& func) {
template <typename T0, typename T1, typename T2, typename R, typename F>
R parallel_sum3d(const T0& D0, const T1& D1, const T2& D2, const R& input, const F& func) {
#if (IE_THREAD == IE_THREAD_TBB || IE_THREAD == IE_THREAD_TBB_AUTO)
return tbb::parallel_reduce(
return tbb::parallel_deterministic_reduce(
tbb::blocked_range3d<T0, T1, T2>(0, D0, 0, D1, 0, D2), input,
[&](const tbb::blocked_range3d<T0, T1, T2>& r, R init) -> R {
R sum = init;
@ -338,11 +339,35 @@ inline void splitter(const T& n, const Q& team, const Q& tid, T& n_start, T& n_e
n_end += n_start;
}
namespace details {
template<typename T>
struct num_of_lambda_args : public num_of_lambda_args<decltype(&T::operator())> {
};
template<typename C, typename R, typename... Args>
struct num_of_lambda_args<R(C::*)(Args...) const> {
constexpr static int value = sizeof...(Args);
};
template<typename ACT, typename ...T, size_t N_ARGS = num_of_lambda_args<ACT>::value>
typename std::enable_if<N_ARGS == sizeof...(T) + 1, void>::type
call_with_args(ACT body, size_t g_id, T ...arg) {
body(g_id, arg...);
}
template<typename ACT, typename ...T, size_t N_ARGS = num_of_lambda_args<ACT>::value>
typename std::enable_if<N_ARGS == sizeof...(T), void>::type
call_with_args(ACT body, size_t g_id, T ...arg) {
body(arg...);
}
} // namespace details
template <typename T0, typename F>
void for_1d(const int& ithr, const int& nthr, const T0& D0, const F& func) {
T0 d0 {0}, end {0};
splitter(D0, nthr, ithr, d0, end);
for (; d0 < end; ++d0) func(d0);
for (; d0 < end; ++d0)
details::call_with_args(func, ithr, d0);
}
template <typename T0, typename F>
@ -385,7 +410,7 @@ void for_2d(const int& ithr, const int& nthr, const T0& D0, const T1& D1, const
T1 d1 {0};
parallel_it_init(start, d0, D0, d1, D1);
for (size_t iwork = start; iwork < end; ++iwork) {
func(d0, d1);
details::call_with_args(func, ithr, d0, d1);
parallel_it_step(d0, D0, d1, D1);
}
}
@ -431,7 +456,7 @@ void for_3d(const int& ithr, const int& nthr, const T0& D0, const T1& D1, const
T2 d2 {0};
parallel_it_init(start, d0, D0, d1, D1, d2, D2);
for (size_t iwork = start; iwork < end; ++iwork) {
func(d0, d1, d2);
details::call_with_args(func, ithr, d0, d1, d2);
parallel_it_step(d0, D0, d1, D1, d2, D2);
}
}
@ -478,7 +503,7 @@ void for_4d(const int& ithr, const int& nthr, const T0& D0, const T1& D1, const
T3 d3 {0};
parallel_it_init(start, d0, D0, d1, D1, d2, D2, d3, D3);
for (size_t iwork = start; iwork < end; ++iwork) {
func(d0, d1, d2, d3);
details::call_with_args(func, ithr, d0, d1, d2, d3);
parallel_it_step(d0, D0, d1, D1, d2, D2, d3, D3);
}
}
@ -527,7 +552,7 @@ void for_5d(const int& ithr, const int& nthr, const T0& D0, const T1& D1, const
T4 d4 {0};
parallel_it_init(start, d0, D0, d1, D1, d2, D2, d3, D3, d4, D4);
for (size_t iwork = start; iwork < end; ++iwork) {
func(d0, d1, d2, d3, d4);
details::call_with_args(func, ithr, d0, d1, d2, d3, d4);
parallel_it_step(d0, D0, d1, D1, d2, D2, d3, D3, d4, D4);
}
}

View File

@ -1125,11 +1125,10 @@ void MKLDNNMVNNode::mvn_blk(const in_data_t* src_data, out_data_t* dst_data, con
for (int i = 0; i < mean_buffer.size(); i++)
mean_buffer[i] = 0.f;
parallel_for2d(D, H, [&](size_t d, size_t h) {
parallel_for2d(D, H, [&](size_t thr_idx, size_t d, size_t h) {
for (size_t cb = 0; cb < CB; cb++) {
size_t src_off = is_nhwc ? ccb + d * H * W * C + h * W * C + cb * blk_size
: ccb + d * H * W * blk_size + h * W * blk_size + cb * D * H * W * blk_size;
auto thr_idx = mkldnn_get_thread_num();
auto mean_buffer_ptr = &mean_buffer[blk_size * cb + aux_buffer_size * thr_idx];
auto arg = jit_mvn_call_args();
@ -1179,11 +1178,10 @@ void MKLDNNMVNNode::mvn_blk(const in_data_t* src_data, out_data_t* dst_data, con
for (int i = 0; i < variance_buffer.size(); i++)
variance_buffer[i] = 0.f;
parallel_for2d(D, H, [&](size_t d, size_t h) {
parallel_for2d(D, H, [&](size_t thr_idx, size_t d, size_t h) {
for (size_t cb = 0; cb < CB; cb++) {
size_t src_off = is_nhwc ? ccb + d * H * W * C + h * W * C + cb * blk_size
: ccb + d * H * W * blk_size + h * W * blk_size + cb * D * H * W * blk_size;
auto thr_idx = mkldnn_get_thread_num();
auto mean_buffer_ptr = &mean_buffer[blk_size * cb];
auto variance_buffer_ptr = &variance_buffer[blk_size * cb + aux_buffer_size * thr_idx];