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

Enable mmap for reading model from cache #26696

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

olpipi
Copy link
Contributor

@olpipi olpipi commented Sep 19, 2024

Details:

  • Enable mmap for reading model from cache

Tickets:

@olpipi olpipi requested review from a team as code owners September 19, 2024 16:33
@github-actions github-actions bot added category: inference OpenVINO Runtime library - Inference category: Core OpenVINO Core (aka ngraph) labels Sep 19, 2024
@olpipi olpipi force-pushed the inport_model_with_mmap branch 2 times, most recently from 8095ad4 to 57a4efa Compare September 19, 2024 16:34
@ilya-lavrenov ilya-lavrenov self-assigned this Sep 19, 2024
@@ -78,7 +80,7 @@ class ICacheManager {
* @param id Id of cache (hash of the model)
* @param reader Lambda function to be called when input stream is created
Copy link
Contributor

Choose a reason for hiding this comment

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

Add new parameter to doxy comment.

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 not new parameter anymore

Copy link
Contributor

Choose a reason for hiding this comment

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

The parameter bool enable_mmap is still here (should it be removed?), sync doxy comment with function signature.

ov::SoPtr<ov::ICompiledModel> compiled_model;
struct HeaderException {};

OPENVINO_ASSERT(cacheContent.cacheManager != nullptr);
try {
cacheContent.cacheManager->read_cache_entry(cacheContent.blobId, [&](std::istream& networkStream) {
cacheContent.cacheManager->read_cache_entry(cacheContent.blobId, enable_mmap, [&](std::istream& networkStream) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
cacheContent.cacheManager->read_cache_entry(cacheContent.blobId, enable_mmap, [&](std::istream& networkStream) {
cacheContent.cacheManager->read_cache_entry(cacheContent.blobId, coreConfig.get_enable_mmap(), [&](std::istream& networkStream) {

The additional parameter enable_mmap can be removed as this member can access core configuration.

Copy link
Contributor Author

@olpipi olpipi Sep 20, 2024

Choose a reason for hiding this comment

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

Unfortunately no. load_model_from_cache is a static method and we cannot get coreConfig.
But why is it static?
@ilya-lavrenov @praasz. Since now this method uses CoreImpl internal state. So can we make it not static? Is there any objections to it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed it to non static const method. Please comment if it not ok

Copy link
Contributor

Choose a reason for hiding this comment

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

The core_impl is internal implementation. There shouldn't be any issue to adjust it to what is required.

SharedStreamBuffer() = delete;

private:
T _shared_object;
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe this class has to not be so generic and shared object can be stored as shared pointer to void.
example

class SharedStreamBuffer final : public std::stringbuf {
public:
    SharedStreamBuffer(char* data, size_t size, std::shared_ptr<void> shared_object) : m_shared_object(std::move(shared_object)) {
        basic_streambuf::pubsetbuf(data, size);
    }

    SharedStreamBuffer() = delete;

private:
    std::shared_ptr<void> m_shared_object;
};

Copy link
Contributor Author

@olpipi olpipi Sep 20, 2024

Choose a reason for hiding this comment

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

I changed it. Now it creates (in RAII manner) SharedBuffer, which already has an implementation to own the shared object

@praasz praasz self-assigned this Sep 20, 2024
@@ -751,7 +751,7 @@ ov::SoPtr<ov::ICompiledModel> ov::CoreImpl::compile_model(const std::shared_ptr<
parsed._config,
ov::SoPtr<ov::IRemoteContext>{},
cacheContent);
});
}, coreConfig.get_enable_mmap());
Copy link
Contributor

Choose a reason for hiding this comment

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

what if config contains enable_mmap(false) while coreConfig has true for the same key?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Lets read it always from config. It is true by default

@olpipi olpipi force-pushed the inport_model_with_mmap branch 2 times, most recently from e73aa8e to 216a980 Compare September 20, 2024 16:02
@@ -78,7 +80,7 @@ class ICacheManager {
* @param id Id of cache (hash of the model)
* @param reader Lambda function to be called when input stream is created
Copy link
Contributor

Choose a reason for hiding this comment

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

The parameter bool enable_mmap is still here (should it be removed?), sync doxy comment with function signature.

@@ -28,4 +28,51 @@ class SharedBuffer : public ov::AlignedBuffer {
T _shared_object;
};

/// \brief SharedStreamBuffer class to store pointer to pre-acclocated buffer and provide streambuf interface.
class SharedStreamBuffer : public std::streambuf {
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider:

  • put this buffer in separate file like string buffer
  • add OPENVINO_API
  • split implementation to hpp/cpp
  • add some unit test (like for string buffer) to test overridden function how they are used.

Just another alternative to integrate it with ov buffer interface.
If multiple inheritance is an issue the composition can be used.

class SharedStreamBuffer : public SharedBuffer<std::shared_ptr<void>>, public std::streambuf {
public:
    SharedStreamBuffer(char* data, size_t size, const std::shared_ptr<void>& shared_object)
        : SharedBuffer<std::shared_ptr<void>>(data, size, shared_object),
          std::streambuf(),
          m_offset(0) {}

protected:
    std::streamsize xsgetn(char* s, std::streamsize count) override {
        auto real_count = std::min<std::streamsize>(showmanyc(), count);
        std::memcpy(s, get_ptr(m_offset), real_count);
        m_offset += real_count;
        return real_count;
    }

    int_type underflow() override {
        return (size() == m_offset) ? traits_type::eof()
                                    : traits_type::to_int_type(*(get_ptr<const char>() + m_offset));
    }

    int_type uflow() override {
        return (size() == m_offset) ? traits_type::eof()
                                    : traits_type::to_int_type(*(get_ptr<const char>() + m_offset++));
    }

    std::streamsize showmanyc() override {
        return size() - m_offset;
    }

private:
    size_t m_offset;
};

}

protected:
std::shared_ptr<AlignedBuffer> m_alligned_buffer;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why shared pointer is required. The ov::SharedBuffer will manage owner ship
Why use aligned buffer not shared?

Suggested change
std::shared_ptr<AlignedBuffer> m_alligned_buffer;
SlignedBuffer m_buffer;

Should be sufficient

: SharedStreamBuffer(data, size),
m_alligned_buffer(std::make_shared<SharedBuffer<T>>(data, size, shared_object)) {}

std::shared_ptr<AlignedBuffer> get_aligned_buffer() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why is required and why not just return internal buffer. When shared buffer used it will just increment counter in stored shared object.

@olpipi olpipi requested review from a team as code owners October 7, 2024 15:23
@github-actions github-actions bot added the category: GPU OpenVINO GPU plugin label Oct 7, 2024
/// \brief SharedStreamBuffer class to store pointer to pre-acclocated buffer and provide streambuf interface.
class SharedStreamBuffer : public std::streambuf {
public:
SharedStreamBuffer(char* data, size_t size) : m_data(data), m_size(size), m_offset(0) {}
Copy link
Contributor

Choose a reason for hiding this comment

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

'data' is not passed to std::streambuf, so operator>> for std::istream should not work in core_impl and HeaderException should be thrown. Actually, it could be done on Linux only, due to the std::streambuf has different implementations depend on OS.
Another way is to define operator>> but you should handle end of line for different OS at least.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
category: Core OpenVINO Core (aka ngraph) category: GPU OpenVINO GPU plugin category: inference OpenVINO Runtime library - Inference
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants