Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement function retrieval APIs; Add documentation for functions #1112

Merged
merged 48 commits into from Jul 19, 2018

Conversation

raymondxyang
Copy link
Contributor

  • Implement function retrieval python APIs on existing ABIs
  • Add documentation generation scripts for functions
  • Minor fixes on dependencies and configurations in CMake files

@@ -57,27 +57,4 @@ class FunctionBuilderRegistry {
static Common::Status function_builder_##counter##_status = \
FunctionBuilderRegistry::OnnxInstance().Register(function_builder);

// Example to register a function.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep it here as an example.

#include "onnx/defs/function.h"
using namespace ONNX_NAMESPACE;

static Common::Status BuildFc(std::unique_ptr<FunctionProto>* func_proto) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's switch MeanVarianceNormalization to be a function. FC was removed/deprecated.

@@ -191,6 +190,14 @@ void OpSchema::Verify(const NodeProto& node) const {
fail_check("Unrecognized attribute: ", name);
}

if (attr_proto.has_ref_attr_name()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this if should be removed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The if logic here determine whether this is a solid attribute or a placeholder attribute. I extract the if- logic here for checks on placeholder attr_proto going under this condition. IMO it is a valid condition checker here.

OpSchemaRegistry::DomainToVersionRange::Instance().Map().at(
func_builder.GetDomain());
op_set.insert({func_builder.GetDomain(),
function_proto->since_version() < version_range.second
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if function's since version is greater than the version_range.second, it should be an error, I think.

CMakeLists.txt Outdated
@@ -30,6 +30,8 @@ list(APPEND CMAKE_MODULE_PATH ${ONNX_ROOT}/cmake/Modules)
if(NOT MSVC)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pthread")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this needed?

@@ -191,6 +190,14 @@ void OpSchema::Verify(const NodeProto& node) const {
fail_check("Unrecognized attribute: ", name, " for operator ", node.op_type());
}

if (attr_proto.has_ref_attr_name()) {
if (!attr_proto.has_type() || attr_proto.type() != expected_type) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks to me this check is also applicable when the attr doesn't have ref_attr_name (however you will need to guard the has_type check by ir_version, IIRC type was added in ir_version 2

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually if it is a solid attr_proto the validation will be covered under checker.cc L199-208.. This validation logic is aimed to be only conducted on the referencing attr_proto.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry if this check is already done in checker, why do we check it again here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no type check for referencing attr_proto, I tested removing this and there is no enforcement for such attr during the registration (ie change attr0->set_type(AttributeProto_AttributeType_INTS) to INT and it can still pass the check)

CMakeLists.txt Outdated
@@ -361,6 +363,7 @@ if (MSVC)
/wd4800 # disable warning type' : forcing value to bool 'true' or 'false' (performance warning)
/wd4503 # identifier' : decorated name length exceeded, name was truncated
/wd4146 # unary minus operator applied to unsigned type, result still unsigned
/wd4244 # conversion from 'protobuf::int64' to 'int'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does such cast happen? do you also need to ignore this warning in other targets?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This happens when I convert fields in functionproto in cpp2py.. I only notice the warning in onnx target..

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least you would also need to ignore it in other platforms as well. maybe what's better is to find the place in pybind11 binding and fix it?

@linkerzhang
Copy link
Member

Thank you!

@@ -96,6 +97,57 @@ PYBIND11_MODULE(onnx_cpp2py_export, onnx_cpp2py_export) {
.value("COMMON", OpSchema::SupportType::COMMON)
.value("EXPERIMENTAL", OpSchema::SupportType::EXPERIMENTAL);

py::class_<FunctionProto> function_proto(defs, "FunctionProto");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not good, because python land already has a FunctionProto class from the auto-generated protobuf python files (onnx.FunctionProto), and its underlying memory layout is totally different from the c++ protobuf structs, and so python land users will see two classes with the same name while they are completely different. what we have been doing when passing protobuf structs across c++ and python is serialize on one side and then deserialize on the other side (look at check_model)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the solution is blocked by #1194 (and seems the import issue is in discussion in protobuf repo as well). I could rename the generated pybind class (to function_schema probably) and explore a way to resolve #1194 (probably need to manually run text replacement scripts), switch to use function_proto later. This class is only used for the display of function information now so there is no use case for users to really create one using function classes in python module.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Found a way to manually correct the import in build. Pushed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment resolved

@raymondxyang raymondxyang force-pushed the function-doc-gen branch 4 times, most recently from 9761f75 to 0ee0adf Compare July 14, 2018 04:44
std::multimap<std::string, std::unique_ptr<FunctionProto>> temp_map;
FunctionBuilderRegistry& function_registry =
FunctionBuilderRegistry::OnnxInstance();
Common::Status status = function_registry.GetFunctions("", &temp_map);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change to use the ONNX_DOMAIN instead of hardcode ""?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed. Thanks for pointing out 👍

onnx/__init__.py Outdated
@@ -6,6 +6,7 @@
from .onnx_pb import * # noqa
from .onnx_operators_pb import * # noqa
from .version import version as __version__ # noqa
from .onnx_operators_pb import * # noqa
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

duplicated

@@ -191,6 +190,14 @@ void OpSchema::Verify(const NodeProto& node) const {
fail_check("Unrecognized attribute: ", name, " for operator ", node.op_type());
}

if (attr_proto.has_ref_attr_name()) {
if (!attr_proto.has_type() || attr_proto.type() != expected_type) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry if this check is already done in checker, why do we check it again here?


if __name__ == '__main__':
base_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
docs_dir = os.path.join(base_dir, 'docs')

class Args(object):
output = os.path.join(docs_dir, 'Operators' + ext)
function_output = os.path.join(docs_dir, 'Functions' + ext)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually how about putting Functions and Operators together?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO the formatting and visualization could be a future task. Currently I am trying to have type/shape inference of function working and may change the visualization accordingly. And we also talked with Netron people and try to have image generated for the functions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good suggestion, let's merge the two documents into one in next PR. Thank you!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all comments except this resolved

from onnx.backend.test.case import collect_snippets
from typing import Text, Sequence, Dict, List, Type, Set, Tuple


SNIPPETS = collect_snippets()
ONNX_ML = bool(os.getenv('ONNX_ML') == '1')
ONNX_DOMAIN = ""
ONNX_ML_DOMAIN = 'ai.onnx.ml'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onnx.defs has ONNX_DOMAIN defined, maybe also move ONNX_ML_DOMAIN to there and here will just refer them through onnx.defs?

@@ -9,13 +9,16 @@
from collections import defaultdict

from onnx import defs
from onnx.defs import OpSchema
from onnx.defs import OpSchema, FunctionProto
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FunctionProto should be imported from onnx

@@ -7,6 +7,7 @@
#include <string>
#include <vector>

#include "onnx/common/constants.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: move this include to function.cc? (since it's used there)

FunctionBuilderRegistry& function_registry =
FunctionBuilderRegistry::OnnxInstance();

Common::Status status =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check status?

std::unordered_map<std::string, std::vector<py::bytes>>::
value_type(iter->first, tmp_vec));
} else {
temp_map.at(iter->first).emplace_back(py::bytes(bytes));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::move bytes?

"Failed to serilize registered function for '" + iter->first +
"'!");
}
if (!temp_map.count(iter->first)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can use [] of unordered_map to implicitly create an entry if the key doesn't already exist.

Copy link
Member

@bddppq bddppq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for patiently addressing all comments!

@raymondxyang
Copy link
Contributor Author

Thanks for the detailed review :)

@linkerzhang linkerzhang merged commit f09d8d6 into onnx:master Jul 19, 2018
hariharans29 pushed a commit to hariharans29/onnx that referenced this pull request Aug 15, 2019
…nnx#1112)

* Add for test function build

* Add pybind functions for getFunction API

* Implement FC function testcase

* Lint code using clang-format

* Disable warning in covert protobuf::int64 to int

* Update doc generation scripts and functions doc

* Trimming some comments

* Fix doc generation scripts for typecheck

* Improve cmake scripts for unittest project dependencies and fix linux build issues

* Lint python code

* Update API to support functions with multiple versions

* Update line ending

* Add changelogs for functions

* Refactor and lint code

* Fix bad linebreaks in markdown files generated

* Resolve PR comments; Refine Function type check implementation

* Add checker for function version; Bump version in onnx_domain

* Update doc_string and generated md files

* Add helper function; Update documents for MVN function

* Fix a bug in MVN function definition

* Experimental: add python test case for MVN

* Update line ends

* Add attribute mvn testcase

* Update generated files on MVN function

* Rename buildnode function

* Remove node part in generated files; Reformat doc_string for MVN

* Fix changelog generation script

* Update MVN testcase to caculate expected output on the fly

* Rephrase description for MVN function

* Formatting docstring for MVN function

* Refactor helper function code; Add epsilon before division

* Move the helper functions into common folder

* Fix typo in function docstring

* Refactor model helper function; Add version check; Fix typo

* Switch to use FunctionProto class generated in python

* Remove unnecessary ignore flag

* Minor fix in c++ tests; Generated function docs for ML domain

* Refactor code to avoid hardcode domain name

* Resolve PR comments
jcwchen pushed a commit to jcwchen/onnx that referenced this pull request Sep 23, 2020
…nnx#1112)

* Add for test function build

* Add pybind functions for getFunction API

* Implement FC function testcase

* Lint code using clang-format

* Disable warning in covert protobuf::int64 to int

* Update doc generation scripts and functions doc

* Trimming some comments

* Fix doc generation scripts for typecheck

* Improve cmake scripts for unittest project dependencies and fix linux build issues

* Lint python code

* Update API to support functions with multiple versions

* Update line ending

* Add changelogs for functions

* Refactor and lint code

* Fix bad linebreaks in markdown files generated

* Resolve PR comments; Refine Function type check implementation

* Add checker for function version; Bump version in onnx_domain

* Update doc_string and generated md files

* Add helper function; Update documents for MVN function

* Fix a bug in MVN function definition

* Experimental: add python test case for MVN

* Update line ends

* Add attribute mvn testcase

* Update generated files on MVN function

* Rename buildnode function

* Remove node part in generated files; Reformat doc_string for MVN

* Fix changelog generation script

* Update MVN testcase to caculate expected output on the fly

* Rephrase description for MVN function

* Formatting docstring for MVN function

* Refactor helper function code; Add epsilon before division

* Move the helper functions into common folder

* Fix typo in function docstring

* Refactor model helper function; Add version check; Fix typo

* Switch to use FunctionProto class generated in python

* Remove unnecessary ignore flag

* Minor fix in c++ tests; Generated function docs for ML domain

* Refactor code to avoid hardcode domain name

* Resolve PR comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants