1 /**
2 * Copyright 2022 Huawei Technologies Co., Ltd
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "tools/common/statistic_utils.h"
18 #if defined(ENABLE_AVX) && defined(__linux__)
19 #include "nnacl/intrinsics/ms_simd_cpu_info.h"
20 #ifdef _MSC_VER
21 #include <immintrin.h>
22 #else
23 #include <x86intrin.h>
24 #endif
25 #endif
26
27 namespace mindspore::lite {
28 #if defined(ENABLE_AVX) && defined(__linux__)
GetFloatMinMaxValueWithSSE(const float * data,int size)29 std::pair<float, float> GetFloatMinMaxValueWithSSE(const float *data, int size) {
30 MS_ASSERT(data != nullptr);
31 MS_ASSERT(size > 0);
32 const int block_size = 4;
33
34 float min_output[4];
35 float max_output[4];
36 __m128 load_data;
37 const float *p = data;
38
39 __m128 min_vals = _mm_set1_ps(FLT_MAX);
40 __m128 max_vals = _mm_set1_ps(-FLT_MAX);
41
42 int index = 0;
43 int block_max_size = size - block_size + 1;
44 for (; index < block_max_size; index += block_size) {
45 load_data = _mm_loadu_ps(p + index);
46 min_vals = _mm_min_ps(min_vals, load_data);
47 max_vals = _mm_max_ps(max_vals, load_data);
48 }
49 _mm_store_ps(min_output, min_vals);
50 _mm_store_ps(max_output, max_vals);
51
52 float min_val = min_output[0];
53 float max_val = max_output[0];
54 for (int i = 1; i < block_size; i++) {
55 min_val = min_val < min_output[i] ? min_val : min_output[i];
56 max_val = max_val > max_output[i] ? max_val : max_output[i];
57 }
58 for (; index < size; index++) {
59 min_val = min_val < p[index] ? min_val : p[index];
60 max_val = max_val > p[index] ? max_val : p[index];
61 }
62 return {min_val, max_val};
63 }
64 #endif
65
GetFloatMinMaxValue(const float * data,int size)66 std::pair<float, float> GetFloatMinMaxValue(const float *data, int size) {
67 #if defined(ENABLE_AVX) && defined(__linux__)
68 if (IntelX86CpuInfoInit() == RET_OK && X86_Sse_Support() && size > 64) {
69 return GetFloatMinMaxValueWithSSE(data, size);
70 } else {
71 return GetMinMaxValue(data, size);
72 }
73 #else
74 return GetMinMaxValue(data, size);
75 #endif
76 }
77 } // namespace mindspore::lite
78