Skip to content

Commit

Permalink
Replace dynamically allocated IntSimdMatrix instances by constants
Browse files Browse the repository at this point in the history
Two header files are no longer needed and could be removed.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
  • Loading branch information
stweil committed Jan 14, 2019
1 parent 26be7c5 commit 605b4d6
Show file tree
Hide file tree
Showing 11 changed files with 35 additions and 105 deletions.
2 changes: 0 additions & 2 deletions CMakeLists.txt
Expand Up @@ -356,8 +356,6 @@ install(FILES
src/arch/dotproductavx.h
src/arch/dotproductsse.h
src/arch/intsimdmatrix.h
src/arch/intsimdmatrixavx2.h
src/arch/intsimdmatrixsse.h
src/arch/simddetect.h

#from ccmain/makefile.am
Expand Down
2 changes: 1 addition & 1 deletion src/arch/Makefile.am
Expand Up @@ -11,7 +11,7 @@ endif
pkginclude_HEADERS =

noinst_HEADERS = dotproduct.h dotproductavx.h dotproductsse.h
noinst_HEADERS += intsimdmatrix.h intsimdmatrixavx2.h intsimdmatrixsse.h
noinst_HEADERS += intsimdmatrix.h
noinst_HEADERS += simddetect.h

noinst_LTLIBRARIES = libtesseract_native.la
Expand Down
11 changes: 6 additions & 5 deletions src/arch/intsimdmatrix.cpp
Expand Up @@ -18,25 +18,26 @@

#include "intsimdmatrix.h"
#include "genericvector.h" // for GenericVector
#include "intsimdmatrixavx2.h" // for IntSimdMatrixAVX2
#include "intsimdmatrixsse.h" // for IntSimdMatrixSSE
#include "matrix.h" // for GENERIC_2D_ARRAY
#include "simddetect.h" // for SIMDDetect

namespace tesseract {

const IntSimdMatrix IntSimdMatrix::IntSimdMatrixNative =
IntSimdMatrix(1, 1, 1, 1, 1, {});

// Factory makes and returns an IntSimdMatrix (sub)class of the best
// available type for the current architecture.
/* static */
const IntSimdMatrix* IntSimdMatrix::GetFastestMultiplier() {
const IntSimdMatrix* multiplier;
if (SIMDDetect::IsAVX2Available()) {
multiplier = new IntSimdMatrixAVX2();
multiplier = &IntSimdMatrixAVX2;
} else if (SIMDDetect::IsSSEAvailable()) {
multiplier = new IntSimdMatrixSSE();
multiplier = &IntSimdMatrixSSE;
} else {
// Default c++ implementation.
multiplier = new IntSimdMatrix(1, 1, 1, 1, 1, {});
multiplier = &IntSimdMatrixNative;
}
return multiplier;
}
Expand Down
4 changes: 4 additions & 0 deletions src/arch/intsimdmatrix.h
Expand Up @@ -115,6 +115,10 @@ class IntSimdMatrix {
const GenericVector<double>& scales, const int8_t* u,
double* v) const;

static const IntSimdMatrix IntSimdMatrixAVX2;
static const IntSimdMatrix IntSimdMatrixSSE;
static const IntSimdMatrix IntSimdMatrixNative;

protected:
// Rounds the input up to a multiple of the given factor.
static int Roundup(int input, int factor) {
Expand Down
12 changes: 5 additions & 7 deletions src/arch/intsimdmatrixavx2.cpp
Expand Up @@ -16,7 +16,7 @@
// limitations under the License.
///////////////////////////////////////////////////////////////////////

#include "intsimdmatrixavx2.h"
#include "intsimdmatrix.h"

#ifdef __AVX2__
#include <immintrin.h>
Expand Down Expand Up @@ -269,14 +269,12 @@ static void PartialMatrixDotVector8(const int8_t* wi, const double* scales,
namespace tesseract {
#endif // __AVX2__

IntSimdMatrixAVX2::IntSimdMatrixAVX2()
#ifdef __AVX2__
: IntSimdMatrix(kNumOutputsPerRegister, kMaxOutputRegisters, kNumInputsPerRegister, kNumInputsPerGroup, kNumInputGroups, {PartialMatrixDotVector64, PartialMatrixDotVector32,
PartialMatrixDotVector16, PartialMatrixDotVector8})
const IntSimdMatrix IntSimdMatrix::IntSimdMatrixAVX2 =
IntSimdMatrix(kNumOutputsPerRegister, kMaxOutputRegisters, kNumInputsPerRegister, kNumInputsPerGroup, kNumInputGroups, {PartialMatrixDotVector64, PartialMatrixDotVector32,
PartialMatrixDotVector16, PartialMatrixDotVector8});
#else
: IntSimdMatrix(1, 1, 1, 1, 1, {})
const IntSimdMatrix IntSimdMatrix::IntSimdMatrixAVX2 = IntSimdMatrix(1, 1, 1, 1, 1, {});
#endif // __AVX2__
{
}

} // namespace tesseract.
33 changes: 0 additions & 33 deletions src/arch/intsimdmatrixavx2.h

This file was deleted.

11 changes: 5 additions & 6 deletions src/arch/intsimdmatrixsse.cpp
Expand Up @@ -15,7 +15,7 @@
// limitations under the License.
///////////////////////////////////////////////////////////////////////

#include "intsimdmatrixsse.h"
#include "intsimdmatrix.h"

#include <cstdint>
#include "dotproductsse.h"
Expand All @@ -33,13 +33,12 @@ static void PartialMatrixDotVector1(const int8_t* wi, const double* scales,
}
#endif // __SSE4_1__

IntSimdMatrixSSE::IntSimdMatrixSSE()
#ifdef __SSE4_1__
: IntSimdMatrix(1, 1, 1, 1, 1, {PartialMatrixDotVector1})
const IntSimdMatrix IntSimdMatrix::IntSimdMatrixSSE =
IntSimdMatrix(1, 1, 1, 1, 1, {PartialMatrixDotVector1});
#else
: IntSimdMatrix(1, 1, 1, 1, 1, {})
const IntSimdMatrix IntSimdMatrix::IntSimdMatrixSSE =
IntSimdMatrix(1, 1, 1, 1, 1, {});
#endif // __SSE4_1__
{
}

} // namespace tesseract.
32 changes: 0 additions & 32 deletions src/arch/intsimdmatrixsse.h

This file was deleted.

4 changes: 2 additions & 2 deletions src/lstm/weightmatrix.cpp
Expand Up @@ -143,7 +143,7 @@ void WeightMatrix::ConvertToInt() {
}
wf_.Resize(1, 1, 0.0);
int_mode_ = true;
multiplier_.reset(IntSimdMatrix::GetFastestMultiplier());
multiplier_ = IntSimdMatrix::GetFastestMultiplier();
multiplier_->Init(wi_, shaped_w_);
}

Expand Down Expand Up @@ -196,7 +196,7 @@ bool WeightMatrix::DeSerialize(bool training, TFile* fp) {
if (int_mode_) {
if (!wi_.DeSerialize(fp)) return false;
if (!scales_.DeSerialize(fp)) return false;
multiplier_.reset(IntSimdMatrix::GetFastestMultiplier());
multiplier_ = IntSimdMatrix::GetFastestMultiplier();
multiplier_->Init(wi_, shaped_w_);
} else {
if (!wf_.DeSerialize(fp)) return false;
Expand Down
4 changes: 2 additions & 2 deletions src/lstm/weightmatrix.h
Expand Up @@ -64,7 +64,7 @@ class TransposedArray : public GENERIC_2D_ARRAY<double> {
// backward steps with the matrix and updates to the weights.
class WeightMatrix {
public:
WeightMatrix() : int_mode_(false), use_adam_(false) {}
WeightMatrix() : int_mode_(false), use_adam_(false), multiplier_(nullptr) {}
// Sets up the network for training. Initializes weights using weights of
// scale `range` picked according to the random number generator `randomizer`.
// Note the order is outputs, inputs, as this is the order of indices to
Expand Down Expand Up @@ -179,7 +179,7 @@ class WeightMatrix {
// The weights matrix reorganized in whatever way suits this instance.
std::vector<int8_t> shaped_w_;
// Holds the optimal integer multiplier for this machine.
std::unique_ptr<const IntSimdMatrix> multiplier_;
const IntSimdMatrix* multiplier_;
};

} // namespace tesseract.
Expand Down
25 changes: 10 additions & 15 deletions unittest/intsimdmatrix_test.cc
Expand Up @@ -18,8 +18,6 @@
#include <memory>
#include "genericvector.h"
#include "include_gunit.h"
#include "intsimdmatrixavx2.h"
#include "intsimdmatrixsse.h"
#include "matrix.h"
#include "simddetect.h"
#include "tprintf.h"
Expand Down Expand Up @@ -56,21 +54,21 @@ class IntSimdMatrixTest : public ::testing::Test {
}
return v;
}
// Tests a range of sizes and compares the results against the base_ version.
void ExpectEqualResults(const IntSimdMatrix* matrix) {
// Tests a range of sizes and compares the results against the generic version.
void ExpectEqualResults(const IntSimdMatrix& matrix) {
double total = 0.0;
for (int num_out = 1; num_out < 130; ++num_out) {
for (int num_in = 1; num_in < 130; ++num_in) {
GENERIC_2D_ARRAY<int8_t> w = InitRandom(num_out, num_in + 1);
std::vector<int8_t> u = RandomVector(num_in, *matrix);
std::vector<int8_t> u = RandomVector(num_in, matrix);
GenericVector<double> scales = RandomScales(num_out);
std::vector<double> base_result(num_out);
std::vector<int8_t> dummy;
base_.MatrixDotVector(w, dummy, scales, u.data(), base_result.data());
IntSimdMatrix::IntSimdMatrixNative.MatrixDotVector(w, dummy, scales, u.data(), base_result.data());
std::vector<double> test_result(num_out);
std::vector<int8_t> shaped_wi;
matrix->Init(w, shaped_wi);
matrix->MatrixDotVector(w, shaped_wi, scales, u.data(), test_result.data());
matrix.Init(w, shaped_wi);
matrix.MatrixDotVector(w, shaped_wi, scales, u.data(), test_result.data());
for (int i = 0; i < num_out; ++i) {
EXPECT_FLOAT_EQ(base_result[i], test_result[i]) << "i=" << i;
total += base_result[i];
Expand All @@ -82,13 +80,12 @@ class IntSimdMatrixTest : public ::testing::Test {
}

TRand random_;
IntSimdMatrix base_ = IntSimdMatrix(1, 1, 1, 1, 1, {});
};

// Test the C++ implementation without SIMD.
TEST_F(IntSimdMatrixTest, C) {
std::unique_ptr<IntSimdMatrix> matrix(new IntSimdMatrix());
ExpectEqualResults(matrix.get());
static const IntSimdMatrix matrix(1, 1, 1, 1, 1, {});
ExpectEqualResults(matrix);
}

// Tests that the SSE implementation gets the same result as the vanilla.
Expand All @@ -99,8 +96,7 @@ TEST_F(IntSimdMatrixTest, SSE) {
tprintf("No SSE found! Not Tested!");
return;
}
std::unique_ptr<IntSimdMatrix> matrix(new IntSimdMatrixSSE());
ExpectEqualResults(matrix.get());
ExpectEqualResults(IntSimdMatrix::IntSimdMatrixSSE);
}

// Tests that the AVX2 implementation gets the same result as the vanilla.
Expand All @@ -111,8 +107,7 @@ TEST_F(IntSimdMatrixTest, AVX2) {
tprintf("No AVX2 found! Not Tested!");
return;
}
std::unique_ptr<IntSimdMatrix> matrix(new IntSimdMatrixAVX2());
ExpectEqualResults(matrix.get());
ExpectEqualResults(IntSimdMatrix::IntSimdMatrixAVX2);
}

} // namespace
Expand Down

0 comments on commit 605b4d6

Please sign in to comment.