-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
[GPU] Graph serialization for GPU #13801
Conversation
37daf88
to
e72ffa4
Compare
2f78667
to
70c3792
Compare
70c3792
to
1cef5bc
Compare
, _impl(nullptr) | ||
, _outputs({memory::ptr()}) | ||
, _output_changed(false) | ||
, _mem_allocated(false) {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this flag be recognized by can_be_optimized?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In most cases, can_be_optimized()
is true when _mem_allocated
is false. But in the case of "implicit concat" for onednn, can_be_optimized()
is false while _mem_allocated
is false.
fd32d54
to
697f7c6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
src/plugins/intel_gpu/src/graph/include/serialization/layout_serializer.hpp
Show resolved
Hide resolved
@@ -901,4 +941,218 @@ std::string primitive_inst::get_implementation_name() const { | |||
return "undef"; | |||
} | |||
|
|||
void primitive_inst::save(cldnn::BinaryOutputBuffer& ob) const { | |||
if (type() == cldnn::data::type_id() || | |||
(type() == cldnn::mutable_data::type_id() && _impl == nullptr)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not override save
method for data/mutable data instead of having branch in common impl?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/openvinotoolkit/openvino/pull/13986/files#r1027065103
I overrided save and load methods for data/mutable data, and removed a branch. Thank you.
if (!_mem_allocated) { | ||
for (size_t dep_idx = 0; dep_idx < _deps.size(); ++dep_idx) { | ||
for (size_t m_idx = 0; m_idx < _deps[dep_idx]->_deps.size(); ++m_idx) { | ||
if (get_network().get_engine().is_the_same_buffer(*_outputs[0], *_deps[dep_idx]->_deps[m_idx]->_outputs[0])) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That logic looks weird and unsafe. If I understand correctly, it assumes that mutable_data is used only asWA for multiple outputs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/openvinotoolkit/openvino/pull/13986/files#r1027035950
I removed this logic as you reviewed. Thank you.
@@ -181,6 +181,11 @@ void CompileModelCacheTestBase::run() { | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such big patch with 0 unit tests is unacceptable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not add unit tests that does not use the IE interfaces (export
and import
) because serialization needs to be saved to a file and then loaded again to see if it works. And the number of newly enabled functional tests related to serialization is more than 200.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked those functional tests and can't say that we can be sure that everything works fine based on them only. E.g. if I change import of CompiledModel::Export to return in the very beginning, then the tests still pass.
Basically, the test check that 1. properties are supported 2. blob file is created; and there is no guarantee that blob file is used or contains expected content
because serialization needs to be saved to a file
Why? As I can see objects are working with ostream/istream, so you can probably you some stream type which is operating in memory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caching functional tests runs the same case three times.
- run without cache at L200
- run to create cache at L219 with i =0
- run with cache at L219 with i =1
Then, it compares the results 1 vs. 2 and 1 vs. 3 at L223
openvino/src/tests/functional/plugin/shared/src/behavior/ov_plugin/caching_tests.cpp
Line 223 in c51ee52
compare(originalOutputs, get_plugin_outputs()); |
But, I agree with you in that we can't say that we can be sure that everything works fine based on them only. I'll add unit tests working on memory as you guided. Thank you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added 38 unit tests for serialization. These tests have export_import
in the test case name. Thank you.
} | ||
|
||
if (idx == _deps.size()) | ||
std::cout << "[get_index_in_deps]: not found" << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? It should be either removed or changed to exception.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/openvinotoolkit/openvino/pull/13986/files#r1024716869
Changed to throw an exception. Thank you.
@@ -762,7 +762,9 @@ void program::cleanup() { | |||
} | |||
} | |||
} | |||
_kernels_cache->reset(); | |||
|
|||
if (_engine.configuration().kernels_cache_path.empty()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/openvinotoolkit/openvino/pull/13986/files#r1021640422
Reverted. Thank you.
@@ -425,6 +426,9 @@ void primitive_inst::set_arguments() { | |||
} | |||
|
|||
void primitive_inst::build_deps() { | |||
if (_node == nullptr) | |||
return; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't exception be thrown here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/openvinotoolkit/openvino/pull/13986/files#r1024718320
Updated to throw an exception when _node is null. Thank you.
int num_data_nodes; | ||
ib >> num_data_nodes; | ||
|
||
_memory_pool->clear_pool_for_network(net_id); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it needed? new mem pool object is created above, so I think clear is redundant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/openvinotoolkit/openvino/pull/13986/files#r1024741591
I removed it. Thank you.
, _internal(false) | ||
, _is_primary_stream(false) | ||
, _reset_arguments(true) { | ||
net_id += 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe net_id is always 1 here which is unexpected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://github.com/openvinotoolkit/openvino/pull/13986/files#r1025253714
I added a new function get_new_net_id() to emit an unique id, and applied it to network ctors. Thank you.
std::string type; | ||
std::string _primitive_id; | ||
ib >> type >> _primitive_id; | ||
std::shared_ptr<cldnn::primitive_inst> new_primitive_inst = cldnn::get_type_id(type)->create_instance(*this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we need to separate data nodes and other node types here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case of deserialization, output memory is allocated whenever each primitive_inst
is restored. At this time, in the case of primitive_inst
that does not allocate memory on its own (_mem_allocated
is false), the memory address of another primitive_inst
is used. In the case of non-data types, there is no problem if they are restored in the order of _exec_order
. But, since data types are not in _exec_order
, memory addresses may not be known unless allocated in advance.
@vladimir-paramuzov Thank you for taking your valuable time to review. I will submit a new PR to address your review. |
@e-ddykim one more issue in cmake output:
|
https://github.com/openvinotoolkit/openvino/pull/13986/files#r1021667835 |
Details:
primitive_inst
andprimitive_impl
.primitive
,program
andprogram_node
are not serialized.Tickets: