diff options
author | Thomas Deutschmann <whissi@gentoo.org> | 2021-03-30 10:59:39 +0200 |
---|---|---|
committer | Thomas Deutschmann <whissi@gentoo.org> | 2021-04-01 00:04:14 +0200 |
commit | 5ff1d6955496b3cf9a35042c9ac35db43bc336b1 (patch) | |
tree | 6d470f7eb448f59f53e8df1010aec9dad8ce1f72 /tesseract/src/arch/intsimdmatrix.cpp | |
parent | Import Ghostscript 9.53.1 (diff) | |
download | ghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.tar.gz ghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.tar.bz2 ghostscript-gpl-patches-5ff1d6955496b3cf9a35042c9ac35db43bc336b1.zip |
Import Ghostscript 9.54ghostscript-9.54
Signed-off-by: Thomas Deutschmann <whissi@gentoo.org>
Diffstat (limited to 'tesseract/src/arch/intsimdmatrix.cpp')
-rw-r--r-- | tesseract/src/arch/intsimdmatrix.cpp | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/tesseract/src/arch/intsimdmatrix.cpp b/tesseract/src/arch/intsimdmatrix.cpp new file mode 100644 index 00000000..6ecb4809 --- /dev/null +++ b/tesseract/src/arch/intsimdmatrix.cpp @@ -0,0 +1,93 @@ +/////////////////////////////////////////////////////////////////////// +// File: intsimdmatrix.cpp +// Description: Base class for 8-bit int SIMD matrix multipliers. +// Author: Ray Smith +// +// (C) Copyright 2017, Google Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/////////////////////////////////////////////////////////////////////// + +#include "intsimdmatrix.h" +#include "matrix.h" // for GENERIC_2D_ARRAY +#include "simddetect.h" // for SIMDDetect + +namespace tesseract { + +const IntSimdMatrix* IntSimdMatrix::intSimdMatrix = nullptr; + +// Computes a reshaped copy of the weight matrix w. +void IntSimdMatrix::Init(const GENERIC_2D_ARRAY<int8_t>& w, + std::vector<int8_t>& shaped_w, + int32_t& rounded_num_out) const { + const int num_out = w.dim1(); + const int num_in = w.dim2() - 1; + // The rounded-up sizes of the reshaped weight matrix, excluding biases. + int rounded_num_in = Roundup(num_in, num_inputs_per_group_); + rounded_num_out = RoundOutputs(num_out); + // Add the bias and compute the required size. + shaped_w.resize((rounded_num_in + 1) * rounded_num_out, 0); + int shaped_index = 0; + int output = 0; + // Each number of registers needs a different format! Iterates over the + // different numbers of registers (each a power of 2). + for (int num_registers = max_output_registers_; num_registers >= 1; + num_registers /= 2) { + // The number of outputs that we will generate with this many registers. + int num_outputs_per_register_set = + num_registers * num_outputs_per_register_; + // Use the max number of registers until we have to go fewer. + while (output + num_outputs_per_register_set <= rounded_num_out) { + // Accumulating outputs in registers saves iterating over the inputs, so + // we only have to do it once per output register set. + for (int input = 0; input < num_in; input += num_inputs_per_group_) { + // Iterate over the number of outputs in a register set. + for (int j = 0; j < num_outputs_per_register_set; ++j) { + // Inner-most loop corresponds to the number of inputs in an input + // group. + for (int i = 0; i < num_inputs_per_group_; ++i) { + int8_t weight = 0; + if (output + j < num_out && input + i < num_in) + weight = w(output + j, input + i); + shaped_w[shaped_index++] = weight; + } + } + } + // Append the bias weights for the register set. + for (int j = 0; j < num_outputs_per_register_set; ++j) { + int8_t weight = 0; + if (output + j < num_out) weight = w(output + j, num_in); + shaped_w[shaped_index++] = weight; + } + output += num_outputs_per_register_set; + } + } +} + +// Computes matrix.vector v = Wu. +// u is of size W.dim2() - 1 and the output v is of size W.dim1(). +// u is imagined to have an extra element at the end with value 1, to +// implement the bias, but it doesn't actually have it. +void IntSimdMatrix::MatrixDotVector(const GENERIC_2D_ARRAY<int8_t>& w, + const std::vector<double>& scales, + const int8_t* u, double* v) { + int num_out = w.dim1(); + int num_in = w.dim2() - 1; + // Base implementation. + for (int i = 0; i < num_out; ++i) { + const int8_t* wi = w[i]; + int total = 0; + for (int j = 0; j < num_in; ++j) total += wi[j] * u[j]; + // Add in the bias and correct for integer values. + v[i] = (total + wi[num_in] * INT8_MAX) * scales[i]; + } +} + +} // namespace tesseract |