xref: /aosp_15_r20/external/XNNPACK/test/rmax-microkernel-tester.h (revision 4bdc94577ba0e567308109d787f7fec7b531ce36)
1*4bdc9457SAndroid Build Coastguard Worker // Copyright (c) Facebook, Inc. and its affiliates.
2*4bdc9457SAndroid Build Coastguard Worker // All rights reserved.
3*4bdc9457SAndroid Build Coastguard Worker //
4*4bdc9457SAndroid Build Coastguard Worker // Copyright 2019 Google LLC
5*4bdc9457SAndroid Build Coastguard Worker //
6*4bdc9457SAndroid Build Coastguard Worker // This source code is licensed under the BSD-style license found in the
7*4bdc9457SAndroid Build Coastguard Worker // LICENSE file in the root directory of this source tree.
8*4bdc9457SAndroid Build Coastguard Worker 
9*4bdc9457SAndroid Build Coastguard Worker #pragma once
10*4bdc9457SAndroid Build Coastguard Worker 
11*4bdc9457SAndroid Build Coastguard Worker #include <gtest/gtest.h>
12*4bdc9457SAndroid Build Coastguard Worker 
13*4bdc9457SAndroid Build Coastguard Worker #include <algorithm>
14*4bdc9457SAndroid Build Coastguard Worker #include <cassert>
15*4bdc9457SAndroid Build Coastguard Worker #include <cstddef>
16*4bdc9457SAndroid Build Coastguard Worker #include <cstdlib>
17*4bdc9457SAndroid Build Coastguard Worker #include <limits>
18*4bdc9457SAndroid Build Coastguard Worker #include <random>
19*4bdc9457SAndroid Build Coastguard Worker #include <vector>
20*4bdc9457SAndroid Build Coastguard Worker 
21*4bdc9457SAndroid Build Coastguard Worker #include <fp16.h>
22*4bdc9457SAndroid Build Coastguard Worker 
23*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack.h>
24*4bdc9457SAndroid Build Coastguard Worker #include <xnnpack/microfnptr.h>
25*4bdc9457SAndroid Build Coastguard Worker 
26*4bdc9457SAndroid Build Coastguard Worker 
27*4bdc9457SAndroid Build Coastguard Worker class RMaxMicrokernelTester {
28*4bdc9457SAndroid Build Coastguard Worker  public:
n(size_t n)29*4bdc9457SAndroid Build Coastguard Worker   inline RMaxMicrokernelTester& n(size_t n) {
30*4bdc9457SAndroid Build Coastguard Worker     assert(n != 0);
31*4bdc9457SAndroid Build Coastguard Worker     this->n_ = n;
32*4bdc9457SAndroid Build Coastguard Worker     return *this;
33*4bdc9457SAndroid Build Coastguard Worker   }
34*4bdc9457SAndroid Build Coastguard Worker 
n()35*4bdc9457SAndroid Build Coastguard Worker   inline size_t n() const {
36*4bdc9457SAndroid Build Coastguard Worker     return this->n_;
37*4bdc9457SAndroid Build Coastguard Worker   }
38*4bdc9457SAndroid Build Coastguard Worker 
iterations(size_t iterations)39*4bdc9457SAndroid Build Coastguard Worker   inline RMaxMicrokernelTester& iterations(size_t iterations) {
40*4bdc9457SAndroid Build Coastguard Worker     this->iterations_ = iterations;
41*4bdc9457SAndroid Build Coastguard Worker     return *this;
42*4bdc9457SAndroid Build Coastguard Worker   }
43*4bdc9457SAndroid Build Coastguard Worker 
iterations()44*4bdc9457SAndroid Build Coastguard Worker   inline size_t iterations() const {
45*4bdc9457SAndroid Build Coastguard Worker     return this->iterations_;
46*4bdc9457SAndroid Build Coastguard Worker   }
47*4bdc9457SAndroid Build Coastguard Worker 
Test(xnn_f16_rmax_ukernel_function rmax)48*4bdc9457SAndroid Build Coastguard Worker   void Test(xnn_f16_rmax_ukernel_function rmax) const {
49*4bdc9457SAndroid Build Coastguard Worker     std::random_device random_device;
50*4bdc9457SAndroid Build Coastguard Worker     auto rng = std::mt19937(random_device());
51*4bdc9457SAndroid Build Coastguard Worker     std::uniform_real_distribution<float> f32dist;
52*4bdc9457SAndroid Build Coastguard Worker 
53*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint16_t> x(n() + XNN_EXTRA_BYTES / sizeof(uint16_t));
54*4bdc9457SAndroid Build Coastguard Worker     for (size_t iteration = 0; iteration < iterations(); iteration++) {
55*4bdc9457SAndroid Build Coastguard Worker       std::generate(x.begin(), x.end(), [&]() { return fp16_ieee_from_fp32_value(f32dist(rng)); });
56*4bdc9457SAndroid Build Coastguard Worker 
57*4bdc9457SAndroid Build Coastguard Worker       // Compute reference results.
58*4bdc9457SAndroid Build Coastguard Worker       float y_ref = -std::numeric_limits<float>::infinity();
59*4bdc9457SAndroid Build Coastguard Worker       for (size_t i = 0; i < n(); i++) {
60*4bdc9457SAndroid Build Coastguard Worker         y_ref = std::max(y_ref, fp16_ieee_to_fp32_value(x[i]));
61*4bdc9457SAndroid Build Coastguard Worker       }
62*4bdc9457SAndroid Build Coastguard Worker 
63*4bdc9457SAndroid Build Coastguard Worker       // Call optimized micro-kernel.
64*4bdc9457SAndroid Build Coastguard Worker       uint16_t y = UINT16_C(0x7E00) /* NaN */;
65*4bdc9457SAndroid Build Coastguard Worker       rmax(n() * sizeof(uint16_t), x.data(), &y);
66*4bdc9457SAndroid Build Coastguard Worker 
67*4bdc9457SAndroid Build Coastguard Worker       // Verify results.
68*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(fp16_ieee_to_fp32_value(y), y_ref)
69*4bdc9457SAndroid Build Coastguard Worker         << "batch " << n() << " y = " << y;
70*4bdc9457SAndroid Build Coastguard Worker     }
71*4bdc9457SAndroid Build Coastguard Worker   }
72*4bdc9457SAndroid Build Coastguard Worker 
Test(xnn_f32_rmax_ukernel_function rmax)73*4bdc9457SAndroid Build Coastguard Worker   void Test(xnn_f32_rmax_ukernel_function rmax) const {
74*4bdc9457SAndroid Build Coastguard Worker     std::random_device random_device;
75*4bdc9457SAndroid Build Coastguard Worker     auto rng = std::mt19937(random_device());
76*4bdc9457SAndroid Build Coastguard Worker     std::uniform_real_distribution<float> f32dist;
77*4bdc9457SAndroid Build Coastguard Worker 
78*4bdc9457SAndroid Build Coastguard Worker     std::vector<float> x(n());
79*4bdc9457SAndroid Build Coastguard Worker     for (size_t iteration = 0; iteration < iterations(); iteration++) {
80*4bdc9457SAndroid Build Coastguard Worker       std::generate(x.begin(), x.end(), [&]() { return f32dist(rng); });
81*4bdc9457SAndroid Build Coastguard Worker 
82*4bdc9457SAndroid Build Coastguard Worker       // Compute reference results.
83*4bdc9457SAndroid Build Coastguard Worker       float y_ref = -std::numeric_limits<float>::infinity();
84*4bdc9457SAndroid Build Coastguard Worker       for (size_t i = 0; i < n(); i++) {
85*4bdc9457SAndroid Build Coastguard Worker         y_ref = std::max(y_ref, x[i]);
86*4bdc9457SAndroid Build Coastguard Worker       }
87*4bdc9457SAndroid Build Coastguard Worker 
88*4bdc9457SAndroid Build Coastguard Worker       // Call optimized micro-kernel.
89*4bdc9457SAndroid Build Coastguard Worker       float y = std::nanf("");
90*4bdc9457SAndroid Build Coastguard Worker       rmax(n() * sizeof(float), x.data(), &y);
91*4bdc9457SAndroid Build Coastguard Worker 
92*4bdc9457SAndroid Build Coastguard Worker       // Verify results.
93*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(y_ref, y)
94*4bdc9457SAndroid Build Coastguard Worker         << "batch " << n();
95*4bdc9457SAndroid Build Coastguard Worker     }
96*4bdc9457SAndroid Build Coastguard Worker   }
97*4bdc9457SAndroid Build Coastguard Worker 
Test(xnn_u8_rmax_ukernel_function rmax)98*4bdc9457SAndroid Build Coastguard Worker   void Test(xnn_u8_rmax_ukernel_function rmax) const {
99*4bdc9457SAndroid Build Coastguard Worker     std::random_device random_device;
100*4bdc9457SAndroid Build Coastguard Worker     auto rng = std::mt19937(random_device());
101*4bdc9457SAndroid Build Coastguard Worker     std::uniform_int_distribution<int32_t> u8dist(
102*4bdc9457SAndroid Build Coastguard Worker       std::numeric_limits<uint8_t>::min(), std::numeric_limits<uint8_t>::max());
103*4bdc9457SAndroid Build Coastguard Worker 
104*4bdc9457SAndroid Build Coastguard Worker     std::vector<uint8_t> x(n());
105*4bdc9457SAndroid Build Coastguard Worker     for (size_t iteration = 0; iteration < iterations(); iteration++) {
106*4bdc9457SAndroid Build Coastguard Worker       std::generate(x.begin(), x.end(), [&]() { return u8dist(rng); });
107*4bdc9457SAndroid Build Coastguard Worker 
108*4bdc9457SAndroid Build Coastguard Worker       // Compute reference results.
109*4bdc9457SAndroid Build Coastguard Worker       uint8_t y_ref = 0;
110*4bdc9457SAndroid Build Coastguard Worker       for (size_t i = 0; i < n(); i++) {
111*4bdc9457SAndroid Build Coastguard Worker         y_ref = std::max(y_ref, x[i]);
112*4bdc9457SAndroid Build Coastguard Worker       }
113*4bdc9457SAndroid Build Coastguard Worker 
114*4bdc9457SAndroid Build Coastguard Worker       // Call optimized micro-kernel.
115*4bdc9457SAndroid Build Coastguard Worker       uint8_t y = u8dist(rng);
116*4bdc9457SAndroid Build Coastguard Worker       rmax(n() * sizeof(uint8_t), x.data(), &y);
117*4bdc9457SAndroid Build Coastguard Worker 
118*4bdc9457SAndroid Build Coastguard Worker       // Verify results.
119*4bdc9457SAndroid Build Coastguard Worker       ASSERT_EQ(int32_t(y_ref), int32_t(y))
120*4bdc9457SAndroid Build Coastguard Worker         << "batch " << n();
121*4bdc9457SAndroid Build Coastguard Worker     }
122*4bdc9457SAndroid Build Coastguard Worker   }
123*4bdc9457SAndroid Build Coastguard Worker 
124*4bdc9457SAndroid Build Coastguard Worker  private:
125*4bdc9457SAndroid Build Coastguard Worker   size_t n_{1};
126*4bdc9457SAndroid Build Coastguard Worker   size_t iterations_{15};
127*4bdc9457SAndroid Build Coastguard Worker };
128