diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2019-04-02 07:31:11 +0000 |
---|---|---|
committer | Henning Baldersheim <balder@yahoo-inc.com> | 2019-04-02 10:01:37 +0000 |
commit | 9a593ba24de74ebf561f31ffee3b373cd10f9148 (patch) | |
tree | 02c3c8019f9ac153527fc37ac4fc53869ab6d58f /eval | |
parent | 6f4adccc7e373b3539441c985ae9499b87148e95 (diff) |
Handle dense tensors encoded as float
Diffstat (limited to 'eval')
11 files changed, 251 insertions, 137 deletions
diff --git a/eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp b/eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp index ae6166f9d24..323aad3246d 100644 --- a/eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp +++ b/eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp @@ -40,6 +40,7 @@ assertTensorSpec(const TensorSpec &expSpec, const Tensor &tensor) struct Fixture { Builder builder; + Fixture() : builder(ValueType::CellType::DOUBLE) {} }; Tensor::UP diff --git a/eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp b/eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp index 7aa1d71fe9a..de860e3b152 100644 --- a/eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp +++ b/eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp @@ -15,6 +15,7 @@ using namespace vespalib::tensor; using vespalib::nbostream; using ExpBuffer = std::vector<uint8_t>; +using CellType = vespalib::eval::ValueType::CellType; namespace std { @@ -69,7 +70,7 @@ struct Fixture Fixture() : _builder() {} Tensor::UP createTensor(const TensorCells &cells) { - return vespalib::tensor::TensorFactory::create(cells, _builder); + return TensorFactory::create(cells, _builder); } Tensor::UP createTensor(const TensorCells &cells, const TensorDimensions &dimensions) { return TensorFactory::create(cells, dimensions, _builder); @@ -146,8 +147,8 @@ TEST_F("test tensor serialization for SparseTensor", SparseFixture) struct DenseFixture { - Tensor::UP createTensor(const DenseTensorCells &cells) { - return TensorFactory::createDense(cells); + Tensor::UP createTensor(CellType cellType, const DenseTensorCells &cells) { + return TensorFactory::createDense(cellType, cells); } void serialize(nbostream &stream, const Tensor &tensor) { @@ -162,7 +163,10 @@ struct DenseFixture return ret; } void assertSerialized(const ExpBuffer &exp, const DenseTensorCells &rhs) { - Tensor::UP rhsTensor(createTensor(rhs)); + assertSerialized(exp, CellType::DOUBLE, rhs); + } + void assertSerialized(const ExpBuffer &exp, CellType cellType, const DenseTensorCells &rhs) { + Tensor::UP rhsTensor(createTensor(cellType, rhs)); nbostream rhsStream; serialize(rhsStream, *rhsTensor); EXPECT_EQUAL(exp, rhsStream); @@ -172,83 +176,103 @@ struct DenseFixture }; -TEST_F("test tensor serialization for DenseTensor", DenseFixture) -{ - TEST_DO(f.assertSerialized({ 0x02, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, +TEST_F("test tensor serialization for DenseTensor", DenseFixture) { + TEST_DO(f.assertSerialized({0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, {})); - TEST_DO(f.assertSerialized({ 0x02, 0x01, 0x01, 0x78, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}, - { {{{"x",0}}, 0} })); - TEST_DO(f.assertSerialized({ 0x02, 0x02, 0x01, 0x78, 0x01, - 0x01, 0x79, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { {{{"x",0},{"y", 0}}, 0} })); - TEST_DO(f.assertSerialized({ 0x02, 0x01, 0x01, 0x78, 0x02, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { {{{"x",1}}, 3} })); - TEST_DO(f.assertSerialized({ 0x02, 0x02, 0x01, 0x78, 0x01, - 0x01, 0x79, 0x01, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { {{{"x",0},{"y",0}}, 3} })); - TEST_DO(f.assertSerialized({ 0x02, 0x02, 0x01, 0x78, 0x02, - 0x01, 0x79, 0x01, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { {{{"x",1},{"y",0}}, 3} })); - TEST_DO(f.assertSerialized({ 0x02, 0x02, 0x01, 0x78, 0x01, - 0x01, 0x79, 0x04, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { {{{"x",0},{"y",3}}, 3} })); - TEST_DO(f.assertSerialized({ 0x02, 0x02, 0x01, 0x78, 0x03, - 0x01, 0x79, 0x05, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x40, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 }, - { {{{"x",2}, {"y",4}}, 3} })); + TEST_DO(f.assertSerialized({0x02, 0x01, 0x01, 0x78, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {{{{"x", 0}}, 0}})); + TEST_DO(f.assertSerialized({0x02, 0x02, 0x01, 0x78, 0x01, + 0x01, 0x79, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {{{{"x", 0}, {"y", 0}}, 0}})); + TEST_DO(f.assertSerialized({0x02, 0x01, 0x01, 0x78, 0x02, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x40, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {{{{"x", 1}}, 3}})); + TEST_DO(f.assertSerialized({0x02, 0x02, 0x01, 0x78, 0x01, + 0x01, 0x79, 0x01, + 0x40, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {{{{"x", 0}, {"y", 0}}, 3}})); + TEST_DO(f.assertSerialized({0x02, 0x02, 0x01, 0x78, 0x02, + 0x01, 0x79, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x40, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {{{{"x", 1}, {"y", 0}}, 3}})); + TEST_DO(f.assertSerialized({0x02, 0x02, 0x01, 0x78, 0x01, + 0x01, 0x79, 0x04, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x40, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {{{{"x", 0}, {"y", 3}}, 3}})); + TEST_DO(f.assertSerialized({0x02, 0x02, 0x01, 0x78, 0x03, + 0x01, 0x79, 0x05, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x40, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00}, + {{{{"x", 2}, {"y", 4}}, 3}})); +} + +TEST_F("test 'float' cells", DenseFixture) { + TEST_DO(f.assertSerialized({0x04, 0x01, 0x02, 0x01, 0x78, 0x03, + 0x01, 0x79, 0x05, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x40, 0x40, 0x00, 0x00 }, + CellType::FLOAT, { {{{"x",2}, {"y",4}}, 3} })); } diff --git a/eval/src/vespa/eval/tensor/default_tensor_engine.cpp b/eval/src/vespa/eval/tensor/default_tensor_engine.cpp index 5a16511fe71..2ac47e35366 100644 --- a/eval/src/vespa/eval/tensor/default_tensor_engine.cpp +++ b/eval/src/vespa/eval/tensor/default_tensor_engine.cpp @@ -138,7 +138,7 @@ DefaultTensorEngine::from_spec(const TensorSpec &spec) const if (is_dense && is_sparse) { return std::make_unique<WrappedSimpleTensor>(eval::SimpleTensor::create(spec)); } else if (is_dense) { - DenseTensorBuilder builder; + DenseTensorBuilder builder(ValueType::CellType::DOUBLE); std::map<vespalib::string,DenseTensorBuilder::Dimension> dimension_map; for (const auto &dimension: type.dimensions()) { dimension_map[dimension.name] = builder.defineDimension(dimension.name, dimension.size); diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_builder.cpp b/eval/src/vespa/eval/tensor/dense/dense_tensor_builder.cpp index 5d52e5f6e0e..c31fef39715 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_tensor_builder.cpp +++ b/eval/src/vespa/eval/tensor/dense/dense_tensor_builder.cpp @@ -37,10 +37,10 @@ validateLabelNotSpecified(size_t oldLabel, const vespalib::string &dimension) } eval::ValueType -makeValueType(std::vector<eval::ValueType::Dimension> &&dimensions) { +makeValueType(eval::ValueType::CellType cellType, std::vector<eval::ValueType::Dimension> &&dimensions) { return (dimensions.empty() ? eval::ValueType::double_type() : - eval::ValueType::tensor_type(std::move(dimensions))); + eval::ValueType::tensor_type(cellType, std::move(dimensions))); } } @@ -93,8 +93,9 @@ DenseTensorBuilder::calculateCellAddress() return result; } -DenseTensorBuilder::DenseTensorBuilder() - : _dimensionsEnum(), +DenseTensorBuilder::DenseTensorBuilder(eval::ValueType::CellType cellType) + : _cellType(cellType), + _dimensionsEnum(), _dimensions(), _cells(), _addressBuilder(), @@ -102,12 +103,10 @@ DenseTensorBuilder::DenseTensorBuilder() { } -DenseTensorBuilder::~DenseTensorBuilder() { -} +DenseTensorBuilder::~DenseTensorBuilder() = default; DenseTensorBuilder::Dimension -DenseTensorBuilder::defineDimension(const vespalib::string &dimension, - size_t dimensionSize) +DenseTensorBuilder::defineDimension(const vespalib::string &dimension, size_t dimensionSize) { auto itr = _dimensionsEnum.find(dimension); if (itr != _dimensionsEnum.end()) { @@ -135,8 +134,7 @@ DenseTensorBuilder::addLabel(Dimension dimension, size_t label) Dimension mappedDimension = _dimensionsMapping[dimension]; const auto &dim = _dimensions[mappedDimension]; validateLabelInRange(label, dim.size, dim.name); - validateLabelNotSpecified(_addressBuilder[mappedDimension], - dim.name); + validateLabelNotSpecified(_addressBuilder[mappedDimension], dim.name); _addressBuilder[mappedDimension] = label; return *this; } @@ -160,8 +158,7 @@ DenseTensorBuilder::build() if (_cells.empty()) { allocateCellsStorage(); } - Tensor::UP result = std::make_unique<DenseTensor>(makeValueType(std::move(_dimensions)), - std::move(_cells)); + Tensor::UP result = std::make_unique<DenseTensor>(makeValueType(_cellType, std::move(_dimensions)), std::move(_cells)); _dimensionsEnum.clear(); _dimensions.clear(); DenseTensor::Cells().swap(_cells); diff --git a/eval/src/vespa/eval/tensor/dense/dense_tensor_builder.h b/eval/src/vespa/eval/tensor/dense/dense_tensor_builder.h index 3969a9335b8..437aaacf8c1 100644 --- a/eval/src/vespa/eval/tensor/dense/dense_tensor_builder.h +++ b/eval/src/vespa/eval/tensor/dense/dense_tensor_builder.h @@ -17,6 +17,7 @@ public: using Dimension = TensorBuilder::Dimension; private: + eval::ValueType::CellType _cellType; vespalib::hash_map<vespalib::string, size_t> _dimensionsEnum; std::vector<eval::ValueType::Dimension> _dimensions; DenseTensor::Cells _cells; @@ -28,7 +29,8 @@ private: size_t calculateCellAddress(); public: - DenseTensorBuilder(); + DenseTensorBuilder() : DenseTensorBuilder(eval::ValueType::CellType::DOUBLE) { } + DenseTensorBuilder(eval::ValueType::CellType cellType); ~DenseTensorBuilder(); Dimension defineDimension(const vespalib::string &dimension, size_t dimensionSize); diff --git a/eval/src/vespa/eval/tensor/serialization/dense_binary_format.cpp b/eval/src/vespa/eval/tensor/serialization/dense_binary_format.cpp index aa4fd702b33..c1fb0dfabc7 100644 --- a/eval/src/vespa/eval/tensor/serialization/dense_binary_format.cpp +++ b/eval/src/vespa/eval/tensor/serialization/dense_binary_format.cpp @@ -3,47 +3,68 @@ #include "dense_binary_format.h" #include <vespa/eval/tensor/dense/dense_tensor.h> #include <vespa/vespalib/objects/nbostream.h> +#include <vespa/vespalib/util/exceptions.h> #include <cassert> using vespalib::nbostream; namespace vespalib::tensor { +using CellType = eval::ValueType::CellType; +using Dimension = eval::ValueType::Dimension; + + namespace { +using EncodeType = DenseBinaryFormat::EncodeType; + +constexpr int DOUBLE_VALUE_TYPE = 0; +constexpr int FLOAT_VALUE_TYPE = 1; + eval::ValueType -makeValueType(std::vector<eval::ValueType::Dimension> &&dimensions) { +makeValueType(CellType cellType, std::vector<Dimension> &&dimensions) { return (dimensions.empty() ? eval::ValueType::double_type() : - eval::ValueType::tensor_type(std::move(dimensions))); -} - + eval::ValueType::tensor_type(cellType, std::move(dimensions))); } -void -DenseBinaryFormat::serialize(nbostream &stream, const DenseTensorView &tensor) -{ - stream.putInt1_4Bytes(tensor.fast_type().dimensions().size()); +size_t +encodeDimensions(nbostream &stream, const eval::ValueType & type) { + stream.putInt1_4Bytes(type.dimensions().size()); size_t cellsSize = 1; - for (const auto &dimension : tensor.fast_type().dimensions()) { + for (const auto &dimension : type.dimensions()) { stream.writeSmallString(dimension.name); stream.putInt1_4Bytes(dimension.size); cellsSize *= dimension.size; } - DenseTensorView::CellsRef cells = tensor.cellsRef(); - assert(cells.size() == cellsSize); + return cellsSize; +} + +template<typename T> +void +encodeCells(nbostream &stream, DenseTensorView::CellsRef cells) { for (const auto &value : cells) { - stream << value; + stream << static_cast<T>(value); } } +void +encodeValueType(nbostream & stream, CellType valueType, EncodeType encodeType) { + switch (valueType) { + case CellType::DOUBLE: + if (encodeType != EncodeType::DOUBLE_IS_DEFAULT) { + stream.putInt1_4Bytes(DOUBLE_VALUE_TYPE); + } + break; + case CellType::FLOAT: + stream.putInt1_4Bytes(FLOAT_VALUE_TYPE); + break; + } +} -std::unique_ptr<DenseTensor> -DenseBinaryFormat::deserialize(nbostream &stream) -{ +size_t +decodeDimensions(nbostream & stream, std::vector<Dimension> & dimensions) { vespalib::string dimensionName; - std::vector<eval::ValueType::Dimension> dimensions; - DenseTensor::Cells cells; size_t dimensionsSize = stream.getInt1_4Bytes(); size_t dimensionSize; size_t cellsSize = 1; @@ -53,14 +74,75 @@ DenseBinaryFormat::deserialize(nbostream &stream) dimensions.emplace_back(dimensionName, dimensionSize); cellsSize *= dimensionSize; } - cells.reserve(cellsSize); - double cellValue = 0.0; + return cellsSize; +} + +CellType +decodeCellType(nbostream & stream, EncodeType encodeType) { + if (encodeType != EncodeType::DOUBLE_IS_DEFAULT) { + uint32_t serializedType = stream.getInt1_4Bytes(); + switch (serializedType) { + case DOUBLE_VALUE_TYPE: + return CellType::DOUBLE; + case FLOAT_VALUE_TYPE: + return CellType::FLOAT; + default: + throw IllegalArgumentException(make_string("Received unknown tensor value type = %u. Only 0(double), or 1(float) are legal.", serializedType)); + } + } else { + return CellType::DOUBLE; + } +} + +template<typename T> +void +decodeCells(nbostream &stream, size_t cellsSize, DenseTensor::Cells & cells) { + T cellValue = 0.0; for (size_t i = 0; i < cellsSize; ++i) { stream >> cellValue; cells.emplace_back(cellValue); } - return std::make_unique<DenseTensor>(makeValueType(std::move(dimensions)), std::move(cells)); } +} + +void +DenseBinaryFormat::serialize(nbostream &stream, const DenseTensorView &tensor) +{ + const eval::ValueType & type = tensor.fast_type(); + encodeValueType(stream, type.cell_type(), _encodeType); + size_t cellsSize = encodeDimensions(stream, type); + + DenseTensorView::CellsRef cells = tensor.cellsRef(); + assert(cells.size() == cellsSize); + switch (type.cell_type()) { + case CellType::DOUBLE: + encodeCells<double>(stream, cells); + break; + case CellType::FLOAT: + encodeCells<float>(stream, cells); + break; + } +} + +std::unique_ptr<DenseTensor> +DenseBinaryFormat::deserialize(nbostream &stream) +{ + CellType cellType = decodeCellType(stream, _encodeType); + std::vector<Dimension> dimensions; + size_t cellsSize = decodeDimensions(stream,dimensions); + DenseTensor::Cells cells; + cells.reserve(cellsSize); + switch (cellType) { + case CellType::DOUBLE: + decodeCells<double>(stream, cellsSize,cells); + break; + case CellType::FLOAT: + decodeCells<float>(stream, cellsSize,cells); + break; + } + + return std::make_unique<DenseTensor>(makeValueType(cellType, std::move(dimensions)), std::move(cells)); +} } diff --git a/eval/src/vespa/eval/tensor/serialization/dense_binary_format.h b/eval/src/vespa/eval/tensor/serialization/dense_binary_format.h index 2f1a53ba567..3f9236ce222 100644 --- a/eval/src/vespa/eval/tensor/serialization/dense_binary_format.h +++ b/eval/src/vespa/eval/tensor/serialization/dense_binary_format.h @@ -16,8 +16,12 @@ class DenseTensorView; class DenseBinaryFormat { public: - static void serialize(nbostream &stream, const DenseTensorView &tensor); - static std::unique_ptr<DenseTensor> deserialize(nbostream &stream); + enum class EncodeType { NO_DEFAULT, DOUBLE_IS_DEFAULT}; + DenseBinaryFormat(EncodeType encodeType) : _encodeType(encodeType) { } + void serialize(nbostream &stream, const DenseTensorView &tensor); + std::unique_ptr<DenseTensor> deserialize(nbostream &stream); +private: + EncodeType _encodeType; }; } diff --git a/eval/src/vespa/eval/tensor/serialization/typed_binary_format.cpp b/eval/src/vespa/eval/tensor/serialization/typed_binary_format.cpp index eb57910a333..f0a9d26fa03 100644 --- a/eval/src/vespa/eval/tensor/serialization/typed_binary_format.cpp +++ b/eval/src/vespa/eval/tensor/serialization/typed_binary_format.cpp @@ -22,8 +22,13 @@ void TypedBinaryFormat::serialize(nbostream &stream, const Tensor &tensor) { if (auto denseTensor = dynamic_cast<const DenseTensorView *>(&tensor)) { - stream.putInt1_4Bytes(DENSE_BINARY_FORMAT_TYPE); - DenseBinaryFormat::serialize(stream, *denseTensor); + if (denseTensor->type().cell_type() != eval::ValueType::CellType::DOUBLE) { + stream.putInt1_4Bytes(TYPED_DENSE_BINARY_FORMAT_TYPE); + DenseBinaryFormat(DenseBinaryFormat::EncodeType::NO_DEFAULT).serialize(stream, *denseTensor); + } else { + stream.putInt1_4Bytes(DENSE_BINARY_FORMAT_TYPE); + DenseBinaryFormat(DenseBinaryFormat::EncodeType::DOUBLE_IS_DEFAULT).serialize(stream, *denseTensor); + } } else if (auto wrapped = dynamic_cast<const WrappedSimpleTensor *>(&tensor)) { eval::SimpleTensor::encode(wrapped->get(), stream); } else { @@ -44,7 +49,10 @@ TypedBinaryFormat::deserialize(nbostream &stream) return builder.build(); } if (formatId == DENSE_BINARY_FORMAT_TYPE) { - return DenseBinaryFormat::deserialize(stream); + return DenseBinaryFormat(DenseBinaryFormat::EncodeType::DOUBLE_IS_DEFAULT).deserialize(stream); + } + if (formatId == TYPED_DENSE_BINARY_FORMAT_TYPE) { + return DenseBinaryFormat(DenseBinaryFormat::EncodeType::NO_DEFAULT).deserialize(stream); } if (formatId == MIXED_BINARY_FORMAT_TYPE) { stream.adjustReadPos(read_pos - stream.rp()); diff --git a/eval/src/vespa/eval/tensor/serialization/typed_binary_format.h b/eval/src/vespa/eval/tensor/serialization/typed_binary_format.h index 334cbe5f564..e40ac7bda43 100644 --- a/eval/src/vespa/eval/tensor/serialization/typed_binary_format.h +++ b/eval/src/vespa/eval/tensor/serialization/typed_binary_format.h @@ -20,6 +20,7 @@ class TypedBinaryFormat static constexpr uint32_t SPARSE_BINARY_FORMAT_TYPE = 1u; static constexpr uint32_t DENSE_BINARY_FORMAT_TYPE = 2u; static constexpr uint32_t MIXED_BINARY_FORMAT_TYPE = 3u; + static constexpr uint32_t TYPED_DENSE_BINARY_FORMAT_TYPE = 4u; public: static void serialize(nbostream &stream, const Tensor &tensor); static std::unique_ptr<Tensor> deserialize(nbostream &stream); diff --git a/eval/src/vespa/eval/tensor/tensor_factory.cpp b/eval/src/vespa/eval/tensor/tensor_factory.cpp index 1e319a45a02..74a84041e75 100644 --- a/eval/src/vespa/eval/tensor/tensor_factory.cpp +++ b/eval/src/vespa/eval/tensor/tensor_factory.cpp @@ -8,8 +8,7 @@ namespace vespalib::tensor { std::unique_ptr<Tensor> -TensorFactory::create(const TensorCells &cells, - TensorBuilder &builder) { +TensorFactory::create(const TensorCells &cells, TensorBuilder &builder) { for (const auto &cell : cells) { for (const auto &addressElem : cell.first) { const auto &dimension = addressElem.first; @@ -29,9 +28,7 @@ TensorFactory::create(const TensorCells &cells, std::unique_ptr<Tensor> -TensorFactory::create(const TensorCells &cells, - const TensorDimensions &dimensions, - TensorBuilder &builder) { +TensorFactory::create(const TensorCells &cells, const TensorDimensions &dimensions, TensorBuilder &builder) { for (const auto &dimension : dimensions) { builder.define_dimension(dimension); } @@ -40,23 +37,18 @@ TensorFactory::create(const TensorCells &cells, std::unique_ptr<Tensor> -TensorFactory::createDense(const DenseTensorCells &cells) +TensorFactory::createDense(eval::ValueType::CellType cellType, const DenseTensorCells &cells) { std::map<std::string, size_t> dimensionSizes; - DenseTensorBuilder builder; + DenseTensorBuilder builder(cellType); for (const auto &cell : cells) { for (const auto &addressElem : cell.first) { - dimensionSizes[addressElem.first] = - std::max(dimensionSizes[addressElem.first], - (addressElem.second + 1)); + dimensionSizes[addressElem.first] = std::max(dimensionSizes[addressElem.first], (addressElem.second + 1)); } } - std::map<std::string, - typename DenseTensorBuilder::Dimension> dimensionEnums; + std::map<std::string, typename DenseTensorBuilder::Dimension> dimensionEnums; for (const auto &dimensionElem : dimensionSizes) { - dimensionEnums[dimensionElem.first] = - builder.defineDimension(dimensionElem.first, - dimensionElem.second); + dimensionEnums[dimensionElem.first] = builder.defineDimension(dimensionElem.first, dimensionElem.second); } for (const auto &cell : cells) { for (const auto &addressElem : cell.first) { diff --git a/eval/src/vespa/eval/tensor/tensor_factory.h b/eval/src/vespa/eval/tensor/tensor_factory.h index 5884255fd59..cd0efdb243e 100644 --- a/eval/src/vespa/eval/tensor/tensor_factory.h +++ b/eval/src/vespa/eval/tensor/tensor_factory.h @@ -19,10 +19,13 @@ public: static std::unique_ptr<Tensor> create(const TensorCells &cells, TensorBuilder &builder); static std::unique_ptr<Tensor> - create(const TensorCells &cells, const TensorDimensions &dimensions, - TensorBuilder &builder); + create(const TensorCells &cells, const TensorDimensions &dimensions, TensorBuilder &builder); static std::unique_ptr<Tensor> - createDense(const DenseTensorCells &cells); + createDense(eval::ValueType::CellType cellType, const DenseTensorCells &cells); + static std::unique_ptr<Tensor> + createDense(const DenseTensorCells &cells) { + return createDense(eval::ValueType::CellType::DOUBLE, cells); + } }; } |