tesseract  4.0.0-1-g2a2b
tesseract::IntSimdMatrix Class Reference

#include <intsimdmatrix.h>

Inheritance diagram for tesseract::IntSimdMatrix:
tesseract::IntSimdMatrixAVX2 tesseract::IntSimdMatrixSSE

Public Member Functions

 IntSimdMatrix ()
 
void Init (const GENERIC_2D_ARRAY< int8_t > &w)
 
int RoundInputs (int size) const
 
int RoundOutputs (int size) const
 
void MatrixDotVector (const GENERIC_2D_ARRAY< int8_t > &w, const GenericVector< double > &scales, const int8_t *u, double *v) const
 

Static Public Member Functions

static IntSimdMatrixGetFastestMultiplier ()
 

Protected Types

typedef void(* PartialFunc) (const int8_t *w, const double *scales, const int8_t *u, int num_in, int num_out, double *v)
 

Static Protected Member Functions

static int Roundup (int input, int factor)
 

Protected Attributes

int num_outputs_per_register_
 
int max_output_registers_
 
int num_inputs_per_register_
 
int num_inputs_per_group_
 
int num_input_groups_
 
std::vector< int8_t > shaped_w_
 
std::vector< PartialFuncpartial_funcs_
 

Detailed Description

Definition at line 61 of file intsimdmatrix.h.

Member Typedef Documentation

◆ PartialFunc

typedef void(* tesseract::IntSimdMatrix::PartialFunc) (const int8_t *w, const double *scales, const int8_t *u, int num_in, int num_out, double *v)
protected

Definition at line 109 of file intsimdmatrix.h.

Constructor & Destructor Documentation

◆ IntSimdMatrix()

tesseract::IntSimdMatrix::IntSimdMatrix ( )
inline

Member Function Documentation

◆ GetFastestMultiplier()

IntSimdMatrix * tesseract::IntSimdMatrix::GetFastestMultiplier ( )
static

Definition at line 31 of file intsimdmatrix.cpp.

31  {
32  IntSimdMatrix* multiplier = nullptr;
34  multiplier = new IntSimdMatrixAVX2();
35  } else if (SIMDDetect::IsSSEAvailable()) {
36  multiplier = new IntSimdMatrixSSE();
37  } else {
38  // Default c++ implementation.
39  multiplier = new IntSimdMatrix();
40  }
41  return multiplier;
42 }
static bool IsSSEAvailable()
Definition: simddetect.h:40
static bool IsAVX2Available()
Definition: simddetect.h:30

◆ Init()

void tesseract::IntSimdMatrix::Init ( const GENERIC_2D_ARRAY< int8_t > &  w)

Definition at line 46 of file intsimdmatrix.cpp.

46  {
47  if (partial_funcs_.empty()) return;
48  int num_out = w.dim1();
49  int num_in = w.dim2() - 1;
50  // The rounded-up sizes of the reshaped weight matrix, excluding biases.
51  int rounded_num_in = Roundup(num_in, num_inputs_per_group_);
52  int rounded_num_out = RoundOutputs(num_out);
53  // Add the bias and compute the required size.
54  shaped_w_.resize((rounded_num_in + 1) * rounded_num_out, 0);
55  int shaped_index = 0;
56  int output = 0;
57  // Each number of registers needs a different format! Iterates over the
58  // different numbers of registers (each a power of 2).
59  for (int num_registers = max_output_registers_; num_registers >= 1;
60  num_registers /= 2) {
61  // The number of outputs that we will generate with this many registers.
62  int num_outputs_per_register_set =
63  num_registers * num_outputs_per_register_;
64  // Use the max number of registers until we have to go fewer.
65  while (output + num_outputs_per_register_set <= rounded_num_out) {
66  // Accumulating outputs in registers saves iterating over the inputs, so
67  // we only have to do it once per output register set.
68  for (int input = 0; input < num_in; input += num_inputs_per_group_) {
69  // Iterate over the number of outputs in a register set.
70  for (int j = 0; j < num_outputs_per_register_set; ++j) {
71  // Inner-most loop corresponds to the number of inputs in an input
72  // group.
73  for (int i = 0; i < num_inputs_per_group_; ++i) {
74  int8_t weight = 0;
75  if (output + j < num_out && input + i < num_in)
76  weight = w(output + j, input + i);
77  shaped_w_[shaped_index++] = weight;
78  }
79  }
80  }
81  // Append the bias weights for the register set.
82  for (int j = 0; j < num_outputs_per_register_set; ++j) {
83  int8_t weight = 0;
84  if (output + j < num_out) weight = w(output + j, num_in);
85  shaped_w_[shaped_index++] = weight;
86  }
87  output += num_outputs_per_register_set;
88  }
89  }
90 }
std::vector< PartialFunc > partial_funcs_
int RoundOutputs(int size) const
Definition: intsimdmatrix.h:85
static int Roundup(int input, int factor)
std::vector< int8_t > shaped_w_
int dim1() const
Definition: matrix.h:206
int dim2() const
Definition: matrix.h:207

◆ MatrixDotVector()

void tesseract::IntSimdMatrix::MatrixDotVector ( const GENERIC_2D_ARRAY< int8_t > &  w,
const GenericVector< double > &  scales,
const int8_t *  u,
double *  v 
) const

Definition at line 96 of file intsimdmatrix.cpp.

98  {
99  int num_out = w.dim1();
100  int num_in = w.dim2() - 1;
101  if (partial_funcs_.empty()) {
102  // Base implementation.
103  for (int i = 0; i < num_out; ++i) {
104  const int8_t* wi = w[i];
105  int total = 0;
106  for (int j = 0; j < num_in; ++j) total += wi[j] * u[j];
107  // Add in the bias and correct for integer values.
108  v[i] = (static_cast<double>(total) / INT8_MAX + wi[num_in]) * scales[i];
109  }
110  } else {
111  const int8_t* w_data = shaped_w_.data();
112  const double* scales_data = &scales[0];
113  // Each call to a partial_func_ produces group_size outputs, except the
114  // last one, which can produce less.
116  int rounded_num_in = Roundup(num_in, num_inputs_per_group_);
117  int rounded_num_out = RoundOutputs(num_out);
118  int output = 0;
119  for (auto fn : partial_funcs_) {
120  // The amount of w_data consumed by each call to fn.
121  int w_step = (rounded_num_in + 1) * group_size;
122  // Run with this group size, until it would produce too much output, then
123  // switch to a smaller size.
124  for (; output + group_size <= rounded_num_out; output += group_size) {
125  (*fn)(w_data, scales_data, u, rounded_num_in, num_out - output, v);
126  w_data += w_step;
127  scales_data += group_size;
128  v += group_size;
129  }
130  group_size /= 2;
131  }
132  }
133 }
std::vector< PartialFunc > partial_funcs_
int RoundOutputs(int size) const
Definition: intsimdmatrix.h:85
static int Roundup(int input, int factor)
std::vector< int8_t > shaped_w_
int dim1() const
Definition: matrix.h:206
int dim2() const
Definition: matrix.h:207

◆ RoundInputs()

int tesseract::IntSimdMatrix::RoundInputs ( int  size) const
inline

Definition at line 81 of file intsimdmatrix.h.

81  {
82  return Roundup(size, num_inputs_per_register_);
83  }
static int Roundup(int input, int factor)

◆ RoundOutputs()

int tesseract::IntSimdMatrix::RoundOutputs ( int  size) const
inline

Definition at line 85 of file intsimdmatrix.h.

85  {
86  return Roundup(size, num_outputs_per_register_);
87  }
static int Roundup(int input, int factor)

◆ Roundup()

static int tesseract::IntSimdMatrix::Roundup ( int  input,
int  factor 
)
inlinestaticprotected

Definition at line 114 of file intsimdmatrix.h.

114  {
115  return (input + factor - 1) / factor * factor;
116  }

Member Data Documentation

◆ max_output_registers_

int tesseract::IntSimdMatrix::max_output_registers_
protected

Definition at line 121 of file intsimdmatrix.h.

◆ num_input_groups_

int tesseract::IntSimdMatrix::num_input_groups_
protected

Definition at line 127 of file intsimdmatrix.h.

◆ num_inputs_per_group_

int tesseract::IntSimdMatrix::num_inputs_per_group_
protected

Definition at line 125 of file intsimdmatrix.h.

◆ num_inputs_per_register_

int tesseract::IntSimdMatrix::num_inputs_per_register_
protected

Definition at line 123 of file intsimdmatrix.h.

◆ num_outputs_per_register_

int tesseract::IntSimdMatrix::num_outputs_per_register_
protected

Definition at line 119 of file intsimdmatrix.h.

◆ partial_funcs_

std::vector<PartialFunc> tesseract::IntSimdMatrix::partial_funcs_
protected

Definition at line 131 of file intsimdmatrix.h.

◆ shaped_w_

std::vector<int8_t> tesseract::IntSimdMatrix::shaped_w_
protected

Definition at line 129 of file intsimdmatrix.h.


The documentation for this class was generated from the following files: