#ifndef CAFFE2_INT8_TEST_UTILS_H_ #define CAFFE2_INT8_TEST_UTILS_H_ #include "caffe2/core/common.h" #include "caffe2/core/context.h" #include "caffe2/core/operator.h" #include "caffe2/core/tensor.h" #include "caffe2/core/tensor_int8.h" #include #include #include #include "gtest/gtest.h" namespace caffe2 { // for quantized Add, the error shouldn't exceed 2 * scale inline float addErrorTolerance(float scale) { return 2 * scale; } inline std::unique_ptr q( const std::vector& dims) { auto r = std::make_unique(); r->scale = 0.01; r->zero_point = static_cast(std::numeric_limits::max()) / 2; ReinitializeTensor(&r->t, dims, at::dtype().device(CPU)); std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution dis{ 0, std::numeric_limits::max()}; for (auto i = 0; i < r->t.numel(); ++i) { r->t.mutable_data()[i] = dis(gen); } return r; } inline std::unique_ptr biasq( const std::vector& dims, double scale) { auto r = std::make_unique(); r->scale = scale; r->zero_point = 0; r->t.Resize(dims); std::random_device rd; std::mt19937 gen(rd()); std::uniform_real_distribution dis(-1, 1); for (auto i = 0; i < r->t.numel(); ++i) { r->t.mutable_data()[i] = static_cast(dis(gen) / scale + r->zero_point); } return r; } inline std::unique_ptr dq(const int8::Int8TensorCPU& XQ) { auto r = std::make_unique(CPU); r->Resize(XQ.t.sizes()); for (auto i = 0; i < r->numel(); ++i) { r->mutable_data()[i] = (static_cast(XQ.t.data()[i]) - XQ.zero_point) * XQ.scale; } return r; } inline std::unique_ptr biasdq(const int8::Int8TensorCPU& XQ) { auto r = std::make_unique(CPU); r->Resize(XQ.t.sizes()); for (auto i = 0; i < r->numel(); ++i) { r->mutable_data()[i] = (XQ.t.data()[i] - XQ.zero_point) * XQ.scale; } return r; } #define EXPECT_TENSOR_EQ(_YA, _YE) \ do { \ EXPECT_TRUE((_YA).sizes() == (_YE).sizes()); \ for (auto i = 0; i < (_YA).numel(); ++i) { \ EXPECT_FLOAT_EQ((_YA).data()[i], (_YE).data()[i]); \ } \ } while (0); #define EXPECT_TENSOR_APPROX_EQ(_YA, _YE, _tol) \ do { \ EXPECT_TRUE((_YA).sizes() == (_YE).sizes()); \ for (auto i = 0; i < (_YA).numel(); ++i) { \ EXPECT_NEAR((_YA).data()[i], (_YE).data()[i], (_tol)); \ } \ } while (0); inline void int8Copy(int8::Int8TensorCPU* dst, const int8::Int8TensorCPU& src) { dst->zero_point = src.zero_point; dst->scale = src.scale; dst->t.CopyFrom(src.t); } inline void add_input( const vector& shape, const vector& values, const string& name, Workspace* ws) { // auto* t = ws->CreateBlob(name)->GetMutable(); auto t = std::make_unique(CPU); t->Resize(shape); std::copy(values.begin(), values.end(), t->mutable_data()); BlobGetMutableTensor(ws->CreateBlob(name), CPU)->CopyFrom(*t); } inline int randomInt(int a, int b) { static std::random_device rd; static std::mt19937 gen(rd()); return std::uniform_int_distribution(a, b)(gen); } } // namespace caffe2 #endif // CAFFE2_INT8_TEST_UTILS_H_