Extend C++ API for Map/Sequence Type Info (#3517) (#4781)

* Extend C++ API for Map/Sequence Type Info (#3517)

Expose functionality to view type information about sequences/maps
to C++ API.

- Add functions
    - `TypeInfo::GetSequenceTypeInfo`
    - `SequenceTypeInfo::GetSequenceElementType`
    - `TypeInfo::GetMapTypeInfo`
    - `MapTypeInfo::GetMapValueType`
    - `MapTypeInfo::GetMapKeyType`
- Add structs
    - `SequenceTypeInfo`
    - `MapTypeInfo`

Co-authored-by: Dudeldu <mustermann.informatik@gmail.com>
Co-authored-by: Jonas-Heinrich <Jonas@JonasHeinrich.com>

* Extend tests to cover new type info functionality for sequences and maps

 - two new test case in test_nontensor_types for maps and sequences

Co-authored-by: Jonas-Heinrich <Jonas@JonasHeinrich.com>
This commit is contained in:
Dudeldu 2020-08-25 21:03:23 +02:00 committed by GitHub
parent 6c26e52134
commit 3d63d8d4f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 114 additions and 0 deletions

View file

@ -74,6 +74,8 @@ ORT_DEFINE_RELEASE(RunOptions);
ORT_DEFINE_RELEASE(Session);
ORT_DEFINE_RELEASE(SessionOptions);
ORT_DEFINE_RELEASE(TensorTypeAndShapeInfo);
ORT_DEFINE_RELEASE(SequenceTypeInfo);
ORT_DEFINE_RELEASE(MapTypeInfo);
ORT_DEFINE_RELEASE(TypeInfo);
ORT_DEFINE_RELEASE(Value);
ORT_DEFINE_RELEASE(ModelMetadata);
@ -285,11 +287,30 @@ struct TensorTypeAndShapeInfo : Base<OrtTensorTypeAndShapeInfo> {
std::vector<int64_t> GetShape() const;
};
struct SequenceTypeInfo : Base<OrtSequenceTypeInfo> {
explicit SequenceTypeInfo(std::nullptr_t) {}
explicit SequenceTypeInfo(OrtSequenceTypeInfo* p) : Base<OrtSequenceTypeInfo>{p} {}
TypeInfo GetSequenceElementType() const;
};
struct MapTypeInfo : Base<OrtMapTypeInfo> {
explicit MapTypeInfo(std::nullptr_t) {}
explicit MapTypeInfo(OrtMapTypeInfo* p) : Base<OrtMapTypeInfo>{p} {}
ONNXTensorElementDataType GetMapKeyType() const;
TypeInfo GetMapValueType() const;
};
struct TypeInfo : Base<OrtTypeInfo> {
explicit TypeInfo(std::nullptr_t) {}
explicit TypeInfo(OrtTypeInfo* p) : Base<OrtTypeInfo>{p} {}
Unowned<TensorTypeAndShapeInfo> GetTensorTypeAndShapeInfo() const;
Unowned<SequenceTypeInfo> GetSequenceTypeInfo() const;
Unowned<MapTypeInfo> GetMapTypeInfo() const;
ONNXType GetONNXType() const;
};

View file

@ -622,6 +622,36 @@ inline Unowned<TensorTypeAndShapeInfo> TypeInfo::GetTensorTypeAndShapeInfo() con
return Unowned<TensorTypeAndShapeInfo>(const_cast<OrtTensorTypeAndShapeInfo*>(out));
}
inline Unowned<SequenceTypeInfo> TypeInfo::GetSequenceTypeInfo() const {
const OrtSequenceTypeInfo* out;
ThrowOnError(GetApi().CastTypeInfoToSequenceTypeInfo(p_, &out));
return Unowned<SequenceTypeInfo>{const_cast<OrtSequenceTypeInfo*>(out)};
}
inline TypeInfo SequenceTypeInfo::GetSequenceElementType() const {
OrtTypeInfo* output;
ThrowOnError(GetApi().GetSequenceElementType(p_, &output));
return TypeInfo{output};
}
inline Unowned<MapTypeInfo> TypeInfo::GetMapTypeInfo() const {
const OrtMapTypeInfo* out;
ThrowOnError(GetApi().CastTypeInfoToMapTypeInfo(p_, &out));
return Unowned<MapTypeInfo>{const_cast<OrtMapTypeInfo*>(out)};
}
inline ONNXTensorElementDataType MapTypeInfo::GetMapKeyType() const {
ONNXTensorElementDataType out;
ThrowOnError(GetApi().GetMapKeyType(p_, &out));
return out;
}
inline TypeInfo MapTypeInfo::GetMapValueType() const {
OrtTypeInfo* output;
ThrowOnError(GetApi().GetMapValueType(p_, &output));
return TypeInfo{output};
}
inline ONNXType TypeInfo::GetONNXType() const {
ONNXType out;
ThrowOnError(GetApi().GetOnnxTypeFromTypeInfo(p_, &out));

View file

@ -150,6 +150,41 @@ TEST(CApiTest, CreateGetVectorOfMapsStringFloat) { // support zipmap output typ
}
}
TEST(CApiTest, TypeInfoMap) {
// Creation
auto default_allocator = onnxruntime::make_unique<MockedOrtAllocator>();
Ort::MemoryInfo info("Cpu", OrtDeviceAllocator, 0, OrtMemTypeDefault);
const int64_t NUM_KV_PAIRS = 4;
std::vector<int64_t> keys{0, 1, 2, 3};
std::vector<int64_t> dims = {NUM_KV_PAIRS};
std::vector<float> values{3.0f, 1.0f, 2.f, 0.f};
// create key tensor
Ort::Value keys_tensor = Ort::Value::CreateTensor(info, keys.data(), keys.size() * sizeof(int64_t),
dims.data(), dims.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64);
// create value tensor
Ort::Value values_tensor = Ort::Value::CreateTensor(info, values.data(), values.size() * sizeof(float),
dims.data(), dims.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT);
Ort::Value map_ort = Ort::Value::CreateMap(keys_tensor, values_tensor);
Ort::TypeInfo type_info = map_ort.GetTypeInfo();
Ort::MapTypeInfo map_type_info = type_info.GetMapTypeInfo();
//Check key type
ASSERT_EQ(map_type_info.GetMapKeyType(), ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64);
Ort::TypeInfo map_value_type_info = map_type_info.GetMapValueType();
//Check value type and shape
ASSERT_EQ(map_value_type_info.GetONNXType(), ONNX_TYPE_TENSOR);
// No shape present, as map values allow different shapes for each element
// ASSERT_EQ(map_value_type_info.GetTensorTypeAndShapeInfo().GetShape(), dims);
ASSERT_EQ(map_value_type_info.GetTensorTypeAndShapeInfo().GetElementType(), ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT);
map_value_type_info.release();
map_type_info.release();
}
TEST(CApiTest, CreateGetSeqTensors) {
// Creation
auto default_allocator = onnxruntime::make_unique<MockedOrtAllocator>();
@ -215,3 +250,31 @@ TEST(CApiTest, CreateGetSeqStringTensors) {
}
ASSERT_EQ(string_set, std::set<std::string>(std::begin(string_input_data), std::end(string_input_data)));
}
TEST(CApiTest, TypeInfoSequence) {
// Creation
auto default_allocator = onnxruntime::make_unique<MockedOrtAllocator>();
Ort::MemoryInfo info("Cpu", OrtDeviceAllocator, 0, OrtMemTypeDefault);
std::vector<Ort::Value> in;
std::vector<int64_t> vals{3, 1, 2, 0};
std::vector<int64_t> dims{1, 4};
const int N = 2;
for (int i = 0; i < N; ++i) {
// create tensor
Ort::Value tensor = Ort::Value::CreateTensor(info, vals.data(), vals.size() * sizeof(int64_t),
dims.data(), dims.size(), ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64);
in.push_back(std::move(tensor));
}
Ort::Value seq_ort = Ort::Value::CreateSequence(in);
Ort::TypeInfo type_info = seq_ort.GetTypeInfo();
Ort::SequenceTypeInfo seq_type_info = type_info.GetSequenceTypeInfo();
ASSERT_EQ(seq_type_info.GetSequenceElementType().GetONNXType(), ONNX_TYPE_TENSOR);
// No shape present, as sequence allows different shapes for each element
// ASSERT_EQ(seq_type_info.GetSequenceElementType().GetTensorTypeAndShapeInfo().GetShape(), dims);
ASSERT_EQ(seq_type_info.GetSequenceElementType().GetTensorTypeAndShapeInfo().GetElementType(), ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64);
seq_type_info.release();
}