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 <array> 15*4bdc9457SAndroid Build Coastguard Worker #include <cassert> 16*4bdc9457SAndroid Build Coastguard Worker #include <cstddef> 17*4bdc9457SAndroid Build Coastguard Worker #include <cstdlib> 18*4bdc9457SAndroid Build Coastguard Worker #include <functional> 19*4bdc9457SAndroid Build Coastguard Worker #include <limits> 20*4bdc9457SAndroid Build Coastguard Worker #include <random> 21*4bdc9457SAndroid Build Coastguard Worker #include <vector> 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 LUTMicrokernelTester { 28*4bdc9457SAndroid Build Coastguard Worker public: batch_size(size_t batch_size)29*4bdc9457SAndroid Build Coastguard Worker inline LUTMicrokernelTester& batch_size(size_t batch_size) { 30*4bdc9457SAndroid Build Coastguard Worker assert(batch_size != 0); 31*4bdc9457SAndroid Build Coastguard Worker this->batch_size_ = batch_size; 32*4bdc9457SAndroid Build Coastguard Worker return *this; 33*4bdc9457SAndroid Build Coastguard Worker } 34*4bdc9457SAndroid Build Coastguard Worker batch_size()35*4bdc9457SAndroid Build Coastguard Worker inline size_t batch_size() const { 36*4bdc9457SAndroid Build Coastguard Worker return this->batch_size_; 37*4bdc9457SAndroid Build Coastguard Worker } 38*4bdc9457SAndroid Build Coastguard Worker inplace(bool inplace)39*4bdc9457SAndroid Build Coastguard Worker inline LUTMicrokernelTester& inplace(bool inplace) { 40*4bdc9457SAndroid Build Coastguard Worker this->inplace_ = inplace; 41*4bdc9457SAndroid Build Coastguard Worker return *this; 42*4bdc9457SAndroid Build Coastguard Worker } 43*4bdc9457SAndroid Build Coastguard Worker inplace()44*4bdc9457SAndroid Build Coastguard Worker inline bool inplace() const { 45*4bdc9457SAndroid Build Coastguard Worker return this->inplace_; 46*4bdc9457SAndroid Build Coastguard Worker } 47*4bdc9457SAndroid Build Coastguard Worker iterations(size_t iterations)48*4bdc9457SAndroid Build Coastguard Worker inline LUTMicrokernelTester& iterations(size_t iterations) { 49*4bdc9457SAndroid Build Coastguard Worker this->iterations_ = iterations; 50*4bdc9457SAndroid Build Coastguard Worker return *this; 51*4bdc9457SAndroid Build Coastguard Worker } 52*4bdc9457SAndroid Build Coastguard Worker iterations()53*4bdc9457SAndroid Build Coastguard Worker inline size_t iterations() const { 54*4bdc9457SAndroid Build Coastguard Worker return this->iterations_; 55*4bdc9457SAndroid Build Coastguard Worker } 56*4bdc9457SAndroid Build Coastguard Worker Test(xnn_x8_lut_ukernel_function lut)57*4bdc9457SAndroid Build Coastguard Worker void Test(xnn_x8_lut_ukernel_function lut) const { 58*4bdc9457SAndroid Build Coastguard Worker std::random_device random_device; 59*4bdc9457SAndroid Build Coastguard Worker auto rng = std::mt19937(random_device()); 60*4bdc9457SAndroid Build Coastguard Worker auto u8rng = std::bind( 61*4bdc9457SAndroid Build Coastguard Worker std::uniform_int_distribution<uint32_t>(0, std::numeric_limits<uint8_t>::max()), std::ref(rng)); 62*4bdc9457SAndroid Build Coastguard Worker 63*4bdc9457SAndroid Build Coastguard Worker std::vector<uint8_t> x(batch_size() + XNN_EXTRA_BYTES / sizeof(uint8_t)); 64*4bdc9457SAndroid Build Coastguard Worker XNN_ALIGN(64) std::array<uint8_t, 256> t; 65*4bdc9457SAndroid Build Coastguard Worker std::vector<uint8_t> y(batch_size() + (inplace() ? XNN_EXTRA_BYTES / sizeof(uint8_t) : 0)); 66*4bdc9457SAndroid Build Coastguard Worker std::vector<uint8_t> y_ref(batch_size()); 67*4bdc9457SAndroid Build Coastguard Worker for (size_t iteration = 0; iteration < iterations(); iteration++) { 68*4bdc9457SAndroid Build Coastguard Worker std::generate(x.begin(), x.end(), std::ref(u8rng)); 69*4bdc9457SAndroid Build Coastguard Worker std::generate(t.begin(), t.end(), std::ref(u8rng)); 70*4bdc9457SAndroid Build Coastguard Worker if (inplace()) { 71*4bdc9457SAndroid Build Coastguard Worker std::generate(y.begin(), y.end(), std::ref(u8rng)); 72*4bdc9457SAndroid Build Coastguard Worker } else { 73*4bdc9457SAndroid Build Coastguard Worker std::fill(y.begin(), y.end(), 0xA5); 74*4bdc9457SAndroid Build Coastguard Worker } 75*4bdc9457SAndroid Build Coastguard Worker const uint8_t* x_data = inplace() ? y.data() : x.data(); 76*4bdc9457SAndroid Build Coastguard Worker 77*4bdc9457SAndroid Build Coastguard Worker // Compute reference results. 78*4bdc9457SAndroid Build Coastguard Worker for (size_t i = 0; i < batch_size(); i++) { 79*4bdc9457SAndroid Build Coastguard Worker y_ref[i] = t[x_data[i]]; 80*4bdc9457SAndroid Build Coastguard Worker } 81*4bdc9457SAndroid Build Coastguard Worker 82*4bdc9457SAndroid Build Coastguard Worker // Call optimized micro-kernel. 83*4bdc9457SAndroid Build Coastguard Worker lut(batch_size(), x_data, y.data(), t.data()); 84*4bdc9457SAndroid Build Coastguard Worker 85*4bdc9457SAndroid Build Coastguard Worker // Verify results. 86*4bdc9457SAndroid Build Coastguard Worker for (size_t i = 0; i < batch_size(); i++) { 87*4bdc9457SAndroid Build Coastguard Worker ASSERT_EQ(uint32_t(y_ref[i]), uint32_t(y[i])) 88*4bdc9457SAndroid Build Coastguard Worker << "at position " << i << " / " << batch_size(); 89*4bdc9457SAndroid Build Coastguard Worker } 90*4bdc9457SAndroid Build Coastguard Worker } 91*4bdc9457SAndroid Build Coastguard Worker } 92*4bdc9457SAndroid Build Coastguard Worker 93*4bdc9457SAndroid Build Coastguard Worker private: 94*4bdc9457SAndroid Build Coastguard Worker size_t batch_size_{1}; 95*4bdc9457SAndroid Build Coastguard Worker bool inplace_{false}; 96*4bdc9457SAndroid Build Coastguard Worker size_t iterations_{15}; 97*4bdc9457SAndroid Build Coastguard Worker }; 98