Skip to content
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 100 additions & 3 deletions include/onnxruntime/core/providers/utils/ort_graph_to_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@
/*out*/ std::vector<int64_t>& dims,
/*out*/ std::vector<std::string>& symbolic_dims);
static Ort::Status OrtValueInfoToProto(const OrtValueInfo& ort_value_info, onnx::ValueInfoProto& value_info_proto);
static Ort::Status OrtOpAttrToProto(const OrtOpAttr& ort_attr, onnx::AttributeProto& attr_proto);
static Ort::Status OrtOpAttrToProto(const OrtNode& ort_node, const OrtOpAttr& ort_attr, onnx::AttributeProto& attr_proto);

Ort::Status OrtGraphToProto(const OrtGraph& ort_graph,
onnx::GraphProto& graph_proto,
Expand Down Expand Up @@ -379,7 +379,7 @@
}

onnx::AttributeProto* attr_proto = node_proto->add_attribute();
ORT_EP_UTILS_CXX_RETURN_IF_ERROR(OrtOpAttrToProto(*ort_attr, *attr_proto));
ORT_EP_UTILS_CXX_RETURN_IF_ERROR(OrtOpAttrToProto(*ort_node, *ort_attr, *attr_proto));
}
}

Expand Down Expand Up @@ -652,7 +652,7 @@
return Ort::Status{nullptr};
}

static Ort::Status OrtOpAttrToProto(const OrtOpAttr& ort_attr, onnx::AttributeProto& attr_proto) {
static Ort::Status OrtOpAttrToProto(const OrtNode& ort_node, const OrtOpAttr& ort_attr, onnx::AttributeProto& attr_proto) {
const OrtApi& ort_api = Ort::GetApi();

const char* attr_name = nullptr;
Expand Down Expand Up @@ -758,6 +758,103 @@

break;
}
case OrtOpAttrType::ORT_OP_ATTR_TENSOR: {
attr_proto.set_type(onnx::AttributeProto_AttributeType_TENSOR);

onnx::TensorProto tensor_proto;

// TensorProto as an attribute value doesn't require a name.

OrtValue* ort_value = nullptr;
ORT_EP_UTILS_C_RETURN_IF_ERROR(ort_api.Node_GetTensorAttributeAsOrtValue(&ort_node, &ort_attr, &ort_value));

Ort::Value tensor(ort_value);

// Get tensor type and shape info
Ort::TensorTypeAndShapeInfo type_shape_info = tensor.GetTensorTypeAndShapeInfo();

// Get tensor type
ONNXTensorElementDataType element_type = type_shape_info.GetElementType();

size_t element_size = 0;
switch (element_type) {
case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_FLOAT);
element_size = sizeof(float);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_UINT8);
element_size = sizeof(uint8_t);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_INT8);
element_size = sizeof(int8_t);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_UINT16);
element_size = sizeof(uint16_t);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_INT16);
element_size = sizeof(int16_t);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_INT32);
element_size = sizeof(int32_t);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_INT64);
element_size = sizeof(int64_t);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_BOOL);
element_size = sizeof(bool);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_DOUBLE);
element_size = sizeof(double);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_UINT32);
element_size = sizeof(uint32_t);
break;
}
case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: {
tensor_proto.set_data_type(onnx::TensorProto_DataType_UINT64);
element_size = sizeof(uint64_t);
break;
}
default: {
std::string err_msg = "Unexpected ONNXTensorElementDataType with value " + std::to_string(static_cast<int>(element_type));
return Ort::Status(err_msg.c_str(), ORT_FAIL);
}
}

auto shape = type_shape_info.GetShape();

for (auto& dim : shape) {
tensor_proto.add_dims(dim);
}

size_t element_count = type_shape_info.GetElementCount();
size_t data_bytes = element_count * element_size;
const void* data = tensor.GetTensorData<void>();

// Copy the Ortvalue to TensorProto as raw data
tensor_proto.set_raw_data(data, data_bytes);
Comment thread
chilo-ms marked this conversation as resolved.

*(attr_proto.mutable_t()) = std::move(tensor_proto);

Check warning on line 855 in include/onnxruntime/core/providers/utils/ort_graph_to_proto.h

View workflow job for this annotation

GitHub Actions / Optional Lint C++

[cpplint] reported by reviewdog 🐶 Add #include <utility> for move [build/include_what_you_use] [4] Raw Output: include/onnxruntime/core/providers/utils/ort_graph_to_proto.h:855: Add #include <utility> for move [build/include_what_you_use] [4]
break;
}
default: {
std::string err_msg = "Unexpected OrtOpAttrType with value " + std::to_string(static_cast<int>(attr_type));
return Ort::Status(err_msg.c_str(), ORT_FAIL);
Expand Down
15 changes: 15 additions & 0 deletions include/onnxruntime/core/session/onnxruntime_c_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ typedef enum OrtOpAttrType {
ORT_OP_ATTR_STRING,
ORT_OP_ATTR_STRINGS,
ORT_OP_ATTR_GRAPH,
ORT_OP_ATTR_TENSOR,
} OrtOpAttrType;

//! @}
Expand Down Expand Up @@ -6065,6 +6066,20 @@ struct OrtApi {
ORT_API2_STATUS(Node_GetAttributeByName, _In_ const OrtNode* node, _In_ const char* attribute_name,
_Outptr_result_maybenull_ const OrtOpAttr** attribute);

/** \brief Get the OrtNode's 'TENSOR' attribute as an OrtValue.
*
* \param[in] node The OrtNode instance.
* \param[in] attribute The OrtOpAttr instance.
* \param[out] attr_tensor Output parameter set to the 'TENSOR' attribute value or nullptr
* if it's not a 'TENSOR' attribute. Must be freed with OrtApi::ReleaseValue.
*
* \snippet{doc} snippets.dox OrtStatus Return Value
*
* \since Version 1.23.
*/
ORT_API2_STATUS(Node_GetTensorAttributeAsOrtValue, _In_ const OrtNode* node, _In_ const OrtOpAttr* attribute,
Comment thread
chilo-ms marked this conversation as resolved.
_Outptr_result_maybenull_ OrtValue** attr_tensor);

/** \brief Get the attribute type as OrtOpAttrType from an OrtOpAttr.
*
* \param[in] attribute The OrtOpAttr instance.
Expand Down
10 changes: 10 additions & 0 deletions onnxruntime/core/graph/abi_graph_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,16 @@ struct OrtNode {
/// <returns>A status indicating success or an error.</returns>
virtual onnxruntime::Status GetAttributes(gsl::span<const OrtOpAttr*> attrs) const = 0;

/// <summary>
/// Gets the node's 'TENSOR' attribute as an OrtValue.
/// </summary>
/// <param name="attr">Node's 'TENSOR' attribute.</param>
/// <param name="value">Output parameter set to the 'TENSOR' attribute value or nullptr
/// if it's not a 'TENSOR' attribute.</param>
/// <returns>A status indicating success or an error.</returns>
virtual onnxruntime::Status GetTensorAttributeAsOrtValue(const OrtOpAttr* attr,
OrtValue** value) const = 0;
Comment thread
edgchen1 marked this conversation as resolved.
Outdated

/// <summary>
/// Gets the number of node subgraphs.
/// </summary>
Expand Down
30 changes: 30 additions & 0 deletions onnxruntime/core/graph/ep_api_types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,36 @@ Status EpNode::GetAttributes(gsl::span<const OrtOpAttr*> dst) const {
return Status::OK();
}

Status EpNode::GetTensorAttributeAsOrtValue(const OrtOpAttr* attribute, OrtValue** result) const {
const auto* attr_proto = reinterpret_cast<const ONNX_NAMESPACE::AttributeProto*>(attribute);

if (attr_proto->type() != onnx::AttributeProto::TENSOR) {
*result = nullptr;
Comment thread
edgchen1 marked this conversation as resolved.
Outdated
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "This OrtOpAttr instance is not a 'TENSOR' attribute");
}

auto tensor_proto_to_ort_value = [&](const ONNX_NAMESPACE::TensorProto& tensor_proto,
OrtValue** result) -> Status {
const auto& graph_viewer = ep_graph_->GetGraphViewer();

// Initialize OrtValue for tensor attribute.
// Note: using std::unique_ptr<OrtValue> because we return a OrtValue* to the user and we want it to be stable.
auto tensor_attribute_value = std::make_unique<OrtValue>();
Comment thread
edgchen1 marked this conversation as resolved.
Outdated
AllocatorPtr tensor_attribute_allocator = CPUAllocator::DefaultInstance();
ORT_RETURN_IF_ERROR(utils::TensorProtoToOrtValue(Env::Default(), graph_viewer.ModelPath(), tensor_proto,
tensor_attribute_allocator, *tensor_attribute_value));

*result = tensor_attribute_value.release();
return Status::OK();
};

const auto& tensor_proto = attr_proto->t();

// Create and returns an OrtValue for the 'TENSOR' attribute
ORT_RETURN_IF_ERROR(tensor_proto_to_ort_value(tensor_proto, result));
return Status::OK();
}

Status EpNode::GetNumSubgraphs(size_t& num_subgraphs) const {
num_subgraphs = subgraphs_.size();
return Status::OK();
Expand Down
4 changes: 4 additions & 0 deletions onnxruntime/core/graph/ep_api_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ struct EpNode : public OrtNode {
// Gets the node's attributes.
Status GetAttributes(gsl::span<const OrtOpAttr*> attrs) const override;

Status GetTensorAttributeAsOrtValue(const OrtOpAttr* attribute,
OrtValue** attr_tensor) const override;

// Gets the number of subgraphs contained by this node.
Status GetNumSubgraphs(size_t& num_subgraphs) const override;

Expand Down Expand Up @@ -228,6 +231,7 @@ struct EpNode : public OrtNode {

std::unordered_map<std::string, std::unique_ptr<ONNX_NAMESPACE::AttributeProto>> attributes_map_;
std::vector<OrtOpAttr*> attributes_;
std::unordered_map<std::string, std::unique_ptr<OrtValue>> tensor_attribute_values_; // The 'TENSOR' Attribute as an OrtValue
Comment thread
edgchen1 marked this conversation as resolved.
Outdated

std::vector<EpValueInfo*> implicit_inputs_;
std::vector<SubgraphState> subgraphs_;
Expand Down
5 changes: 5 additions & 0 deletions onnxruntime/core/graph/model_editor_api_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ struct ModelEditorNode : public OrtNode {
"OrtModelEditorApi does not support getting attribute OrtOpAttr for OrtNode");
}

Status GetTensorAttributeAsOrtValue(const OrtOpAttr* /*attribute*/, OrtValue** /*attr_tensor*/) const override {
return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED,
"OrtModelEditorApi does not support getting 'TENSOR' attribute for OrtNode");
}

Status GetNumSubgraphs(size_t& /*num_subgraphs*/) const override {
return ORT_MAKE_STATUS(ONNXRUNTIME, NOT_IMPLEMENTED,
"OrtModelEditorApi does not support getting the subgraphs for OrtNode");
Expand Down
26 changes: 26 additions & 0 deletions onnxruntime/core/session/onnxruntime_c_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3018,6 +3018,27 @@ ORT_API_STATUS_IMPL(OrtApis::Node_GetAttributeByName, _In_ const OrtNode* node,
API_IMPL_END
}

ORT_API_STATUS_IMPL(OrtApis::Node_GetTensorAttributeAsOrtValue, _In_ const OrtNode* node, _In_ const OrtOpAttr* attribute, _Outptr_result_maybenull_ OrtValue** attr_tensor) {
API_IMPL_BEGIN
if (attr_tensor == nullptr) {
return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "attr_tensor argument is null");
}
if (attribute == nullptr) {
return OrtApis::CreateStatus(ORT_INVALID_ARGUMENT, "attribute argument is null");
}

const auto& tensor_proto = reinterpret_cast<const ONNX_NAMESPACE::AttributeProto*>(attribute)->t();

ORT_ENFORCE(utils::HasDataType(tensor_proto), "Tensor proto doesn't have data type.");
ORT_ENFORCE(ONNX_NAMESPACE::TensorProto::DataType_IsValid(tensor_proto.data_type()), "Tensor proto has invalid data type.");
ORT_ENFORCE(!utils::HasExternalData(tensor_proto),
"Tensor proto with external data for value attribute is not supported.");
Comment thread
adrianlizarraga marked this conversation as resolved.
Outdated

ORT_API_RETURN_IF_STATUS_NOT_OK(node->GetTensorAttributeAsOrtValue(attribute, attr_tensor));
return nullptr;
API_IMPL_END
}

ORT_API_STATUS_IMPL(OrtApis::OpAttr_GetType, _In_ const OrtOpAttr* attribute, _Out_ OrtOpAttrType* type) {
API_IMPL_BEGIN
const auto attr = attribute->attr_proto;
Expand Down Expand Up @@ -3055,6 +3076,10 @@ ORT_API_STATUS_IMPL(OrtApis::OpAttr_GetType, _In_ const OrtOpAttr* attribute, _O
*type = OrtOpAttrType::ORT_OP_ATTR_GRAPH;
break;
}
case ONNX_NAMESPACE::AttributeProto_AttributeType::AttributeProto_AttributeType_TENSOR: {
*type = OrtOpAttrType::ORT_OP_ATTR_TENSOR;
break;
}
default:
return OrtApis::CreateStatus(OrtErrorCode::ORT_INVALID_ARGUMENT, "Unexpected attribute type.");
}
Expand Down Expand Up @@ -4037,6 +4062,7 @@ static constexpr OrtApi ort_api_1_to_23 = {
&OrtApis::Node_GetNumAttributes,
&OrtApis::Node_GetAttributes,
&OrtApis::Node_GetAttributeByName,
&OrtApis::Node_GetTensorAttributeAsOrtValue,
&OrtApis::OpAttr_GetType,
&OrtApis::OpAttr_GetName,
&OrtApis::Node_GetNumSubgraphs,
Expand Down
2 changes: 2 additions & 0 deletions onnxruntime/core/session/ort_apis.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,8 @@ ORT_API_STATUS_IMPL(Node_GetAttributes, _In_ const OrtNode* node,
_Out_writes_(num_attributes) const OrtOpAttr** attributes, _In_ size_t num_attributes);
ORT_API_STATUS_IMPL(Node_GetAttributeByName, _In_ const OrtNode* node, _In_ const char* attribute_name,
_Outptr_result_maybenull_ const OrtOpAttr** attribute);
ORT_API_STATUS_IMPL(Node_GetTensorAttributeAsOrtValue, _In_ const OrtNode* node, _In_ const OrtOpAttr* attribute,
_Outptr_result_maybenull_ OrtValue** attr_tensor);
ORT_API_STATUS_IMPL(OpAttr_GetType, _In_ const OrtOpAttr* attribute, _Out_ OrtOpAttrType* type);
ORT_API_STATUS_IMPL(OpAttr_GetName, _In_ const OrtOpAttr* attribute, _Outptr_ const char** name);
ORT_API_STATUS_IMPL(Node_GetNumSubgraphs, _In_ const OrtNode* node, _Out_ size_t* num_subgraphs);
Expand Down
Loading
Loading