summaryrefslogtreecommitdiffstats
path: root/eval
diff options
context:
space:
mode:
authorHenning Baldersheim <balder@yahoo-inc.com>2019-04-02 07:31:11 +0000
committerHenning Baldersheim <balder@yahoo-inc.com>2019-04-02 10:01:37 +0000
commit9a593ba24de74ebf561f31ffee3b373cd10f9148 (patch)
tree02c3c8019f9ac153527fc37ac4fc53869ab6d58f /eval
parent6f4adccc7e373b3539441c985ae9499b87148e95 (diff)
Handle dense tensors encoded as float
Diffstat (limited to 'eval')
-rw-r--r--eval/src/tests/tensor/dense_tensor_builder/dense_tensor_builder_test.cpp1
-rw-r--r--eval/src/tests/tensor/tensor_serialization/tensor_serialization_test.cpp184
-rw-r--r--eval/src/vespa/eval/tensor/default_tensor_engine.cpp2
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_tensor_builder.cpp21
-rw-r--r--eval/src/vespa/eval/tensor/dense/dense_tensor_builder.h4
-rw-r--r--eval/src/vespa/eval/tensor/serialization/dense_binary_format.cpp122
-rw-r--r--eval/src/vespa/eval/tensor/serialization/dense_binary_format.h8
-rw-r--r--eval/src/vespa/eval/tensor/serialization/typed_binary_format.cpp14
-rw-r--r--eval/src/vespa/eval/tensor/serialization/typed_binary_format.h1
-rw-r--r--eval/src/vespa/eval/tensor/tensor_factory.cpp22
-rw-r--r--eval/src/vespa/eval/tensor/tensor_factory.h9
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);
+ }
};
}