|
19 | 19 | #include "fbgemm/FloatConversion.h" |
20 | 20 | #include "fbgemm/Types.h" |
21 | 21 |
|
| 22 | +#if defined(__x86_64__) || defined(__i386__) || \ |
| 23 | + (defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))) |
| 24 | +#include <immintrin.h> |
| 25 | +#endif |
| 26 | + |
22 | 27 | namespace fbgemm { |
23 | 28 |
|
24 | 29 | using namespace std; |
@@ -196,6 +201,43 @@ void ChooseRequantizationMultiplier( |
196 | 201 | //////////////////////////////////////////////////////////////////////////////// |
197 | 202 | // Utility functions |
198 | 203 |
|
| 204 | +void FindMinMax(const float* m, float* min, float* max, int64_t len) { |
| 205 | + if (len <= 0) { |
| 206 | + *min = 0.0f; |
| 207 | + *max = 0.0f; |
| 208 | + return; |
| 209 | + } |
| 210 | + |
| 211 | + float temp_min = *m, temp_max = *m; |
| 212 | + int64_t i = 0; |
| 213 | + |
| 214 | +#ifdef __AVX__ |
| 215 | + __m256 min_v = _mm256_set1_ps(*m), max_v = _mm256_set1_ps(*m); |
| 216 | + constexpr int VLEN = 8; |
| 217 | + if (len >= VLEN) { |
| 218 | + for (; i < len / VLEN * VLEN; i += VLEN) { |
| 219 | + min_v = _mm256_min_ps(min_v, _mm256_loadu_ps(m + i)); |
| 220 | + max_v = _mm256_max_ps(max_v, _mm256_loadu_ps(m + i)); |
| 221 | + } |
| 222 | + |
| 223 | + float min_buf[VLEN], max_buf[VLEN]; |
| 224 | + _mm256_storeu_ps(min_buf, min_v); |
| 225 | + _mm256_storeu_ps(max_buf, max_v); |
| 226 | + for (int j = 0; j < VLEN; ++j) { |
| 227 | + temp_min = std::min(temp_min, min_buf[j]); |
| 228 | + temp_max = std::max(temp_max, max_buf[j]); |
| 229 | + } |
| 230 | + } |
| 231 | +#endif |
| 232 | + |
| 233 | + for (; i < len; i++) { |
| 234 | + temp_min = std::min(temp_min, m[i]); |
| 235 | + temp_max = std::max(temp_max, m[i]); |
| 236 | + } |
| 237 | + *min = temp_min; |
| 238 | + *max = temp_max; |
| 239 | +} |
| 240 | + |
199 | 241 | #define FBGEMM_SPECIALIZED_QUANTIZE(T, LEGACY) \ |
200 | 242 | template <> \ |
201 | 243 | FBGEMM_API void Quantize<T, LEGACY>( \ |
|
0 commit comments