tesseract  5.0.0-alpha-619-ge9db
intsimdmatrix.cpp
Go to the documentation of this file.
1 // File: intsimdmatrix.cpp
3 // Description: Base class for 8-bit int SIMD matrix multipliers.
4 // Author: Ray Smith
5 // Created: Tue Aug 15 08:01:32 PST 2017
6 //
7 // (C) Copyright 2017, Google Inc.
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
12 // Unless required by applicable law or agreed to in writing, software
13 // distributed under the License is distributed on an "AS IS" BASIS,
14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 // See the License for the specific language governing permissions and
16 // limitations under the License.
18 
19 #include "intsimdmatrix.h"
20 #include <tesseract/genericvector.h> // for GenericVector
21 #include "matrix.h" // for GENERIC_2D_ARRAY
22 #include "simddetect.h" // for SIMDDetect
23 
24 namespace tesseract {
25 
26 const IntSimdMatrix* IntSimdMatrix::intSimdMatrix = nullptr;
27 
28 // Computes a reshaped copy of the weight matrix w.
30  std::vector<int8_t>& shaped_w) const {
31  const int num_out = w.dim1();
32  const int num_in = w.dim2() - 1;
33  // The rounded-up sizes of the reshaped weight matrix, excluding biases.
34  int rounded_num_in = Roundup(num_in, num_inputs_per_group_);
35  int rounded_num_out = RoundOutputs(num_out);
36  // Add the bias and compute the required size.
37  shaped_w.resize((rounded_num_in + 1) * rounded_num_out, 0);
38  int shaped_index = 0;
39  int output = 0;
40  // Each number of registers needs a different format! Iterates over the
41  // different numbers of registers (each a power of 2).
42  for (int num_registers = max_output_registers_; num_registers >= 1;
43  num_registers /= 2) {
44  // The number of outputs that we will generate with this many registers.
45  int num_outputs_per_register_set =
46  num_registers * num_outputs_per_register_;
47  // Use the max number of registers until we have to go fewer.
48  while (output + num_outputs_per_register_set <= rounded_num_out) {
49  // Accumulating outputs in registers saves iterating over the inputs, so
50  // we only have to do it once per output register set.
51  for (int input = 0; input < num_in; input += num_inputs_per_group_) {
52  // Iterate over the number of outputs in a register set.
53  for (int j = 0; j < num_outputs_per_register_set; ++j) {
54  // Inner-most loop corresponds to the number of inputs in an input
55  // group.
56  for (int i = 0; i < num_inputs_per_group_; ++i) {
57  int8_t weight = 0;
58  if (output + j < num_out && input + i < num_in)
59  weight = w(output + j, input + i);
60  shaped_w[shaped_index++] = weight;
61  }
62  }
63  }
64  // Append the bias weights for the register set.
65  for (int j = 0; j < num_outputs_per_register_set; ++j) {
66  int8_t weight = 0;
67  if (output + j < num_out) weight = w(output + j, num_in);
68  shaped_w[shaped_index++] = weight;
69  }
70  output += num_outputs_per_register_set;
71  }
72  }
73 }
74 
75 // Computes matrix.vector v = Wu.
76 // u is of size W.dim2() - 1 and the output v is of size W.dim1().
77 // u is imagined to have an extra element at the end with value 1, to
78 // implement the bias, but it doesn't actually have it.
80  const GenericVector<double>& scales,
81  const int8_t* u, double* v) {
82  int num_out = w.dim1();
83  int num_in = w.dim2() - 1;
84  // Base implementation.
85  for (int i = 0; i < num_out; ++i) {
86  const int8_t* wi = w[i];
87  int total = 0;
88  for (int j = 0; j < num_in; ++j) total += wi[j] * u[j];
89  // Add in the bias and correct for integer values.
90  v[i] = (static_cast<double>(total) / INT8_MAX + wi[num_in]) * scales[i];
91  }
92 }
93 
94 } // namespace tesseract
tesseract::IntSimdMatrix::num_inputs_per_group_
int num_inputs_per_group_
Definition: intsimdmatrix.h:112
tesseract::IntSimdMatrix::Init
void Init(const GENERIC_2D_ARRAY< int8_t > &w, std::vector< int8_t > &shaped_w) const
Definition: intsimdmatrix.cpp:29
simddetect.h
tesseract::IntSimdMatrix::RoundOutputs
int RoundOutputs(int size) const
Definition: intsimdmatrix.h:73
GENERIC_2D_ARRAY< int8_t >
tesseract::IntSimdMatrix::max_output_registers_
int max_output_registers_
Definition: intsimdmatrix.h:108
tesseract::IntSimdMatrix::Roundup
static int Roundup(int input, int factor)
Definition: intsimdmatrix.h:87
genericvector.h
GENERIC_2D_ARRAY::dim2
int dim2() const
Definition: matrix.h:206
matrix.h
tesseract::IntSimdMatrix::intSimdMatrix
static const IntSimdMatrix * intSimdMatrix
Definition: intsimdmatrix.h:116
tesseract
Definition: baseapi.h:65
GenericVector< double >
tesseract::IntSimdMatrix::MatrixDotVector
static void MatrixDotVector(const GENERIC_2D_ARRAY< int8_t > &w, const GenericVector< double > &scales, const int8_t *u, double *v)
Definition: intsimdmatrix.cpp:79
tesseract::IntSimdMatrix::num_outputs_per_register_
int num_outputs_per_register_
Definition: intsimdmatrix.h:106
intsimdmatrix.h
GENERIC_2D_ARRAY::dim1
int dim1() const
Definition: matrix.h:205