Skip to content
Open
Show file tree
Hide file tree
Changes from 84 commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
a7986c7
Add OCL remote tensor creation from file
artemisTurintech Jul 30, 2026
0b7a358
Retain mapped data in OCL buffer tensor
artemisTurintech Jul 30, 2026
f28d994
Keep file mapping alive for OCL buffer tensor
artemisTurintech Jul 30, 2026
4acc8a7
Keep mapped file data alive for OCL tensor
artemisTurintech Jul 30, 2026
b6c4078
Include file stream for OCL file tensor test
artemisTurintech Jul 30, 2026
a9bf0fd
Test OCL remote tensor creation from file
artemisTurintech Jul 30, 2026
98bf157
Include filesystem for OCL file tensor API
artemisTurintech Jul 30, 2026
3ead730
Include filesystem for OCL file tensor test
artemisTurintech Jul 30, 2026
419fd30
Add offset to OCL file tensor creation
artemisTurintech Jul 30, 2026
7bf2f39
Keep OCL file tensor API lightweight
artemisTurintech Jul 30, 2026
bf129a3
Remove file mapping state from OCL buffer tensor
artemisTurintech Jul 30, 2026
86e1809
Restore OCL buffer tensor wrapper
artemisTurintech Jul 30, 2026
1094be6
Use direct mapped data for OCL file tensor
artemisTurintech Jul 30, 2026
3e1b395
Exercise OCL file tensor offset
artemisTurintech Jul 30, 2026
74595d4
Create OCL file tensor with offset
artemisTurintech Jul 30, 2026
2b75fb4
Document OCL remote tensor creation from file
artemisTurintech Jul 30, 2026
86f83e2
Document file tensor offset
artemisTurintech Jul 30, 2026
6011f1b
Include filesystem for GPU file descriptor property
artemisTurintech Jul 30, 2026
b8c7729
Add MMAPED_FILE shared mem type for GPU
artemisTurintech Jul 30, 2026
deeb642
Serialize MMAPED_FILE shared mem type
artemisTurintech Jul 30, 2026
2477fd5
Deserialize MMAPED_FILE shared mem type
artemisTurintech Jul 30, 2026
acffc73
Include GPU debug logging in ocl_engine
artemisTurintech Jul 30, 2026
ade06dc
Log host buffer creation in ocl_engine
artemisTurintech Jul 30, 2026
b698fdd
Add FileDescriptor and mmap file properties for GPU
artemisTurintech Jul 30, 2026
55d73a0
Route OCL file tensor through plugin mmap path
artemisTurintech Jul 30, 2026
329a3a8
Include ov::Tensor for mmap keep-alive
artemisTurintech Jul 30, 2026
1708c08
Accept mmap tensor keep-alive in remote tensor
artemisTurintech Jul 30, 2026
ff78ef5
Store mmap tensor keep-alive in remote tensor
artemisTurintech Jul 30, 2026
c257ee5
Keep file mapping alive in remote tensor ctor
artemisTurintech Jul 30, 2026
f0e0fe4
Include read_tensor_data for GPU mmap tensor
artemisTurintech Jul 30, 2026
12b928d
Handle MMAPED_FILE shared memory type
artemisTurintech Jul 30, 2026
562dc5e
Add file-mapped remote tensor creation
artemisTurintech Jul 30, 2026
45b0b57
Declare file-mapped remote tensor helper
artemisTurintech Jul 30, 2026
1dd3990
Expose FileDescriptor alias in ocl namespace
artemisTurintech Jul 30, 2026
d3a4fa0
Use FileDescriptor for OCL file tensor API
artemisTurintech Jul 30, 2026
b554fd3
Drop unused filesystem include in ocl header
artemisTurintech Jul 30, 2026
4228c84
Use FileDescriptor in OCL file tensor test
artemisTurintech Jul 30, 2026
d17f441
Document FileDescriptor-based GPU file tensor
artemisTurintech Jul 30, 2026
278e026
Document file-backed remote tensor creation tab
artemisTurintech Jul 30, 2026
fea3da0
Make OCL file tensor test run inference
artemisTurintech Jul 30, 2026
ef652b4
Drop unused debug include in ocl_engine
artemisTurintech Jul 30, 2026
6a0d597
Remove unnecessary host buffer logging
artemisTurintech Jul 30, 2026
73f729f
Log memory when wrapping file-mapped host buffer
artemisTurintech Jul 30, 2026
9f4f4be
Hash mmap tensor data pointer in remote tensor
artemisTurintech Jul 30, 2026
6bc3ccf
Remove file-mapped host buffer debug trace
artemisTurintech Jul 30, 2026
0742fa7
Add track_memory flag to create_hostbuffer
artemisTurintech Jul 30, 2026
7bf3b3d
Add track_memory flag to ocl create_hostbuffer
artemisTurintech Jul 30, 2026
5407ead
Add track_memory flag to create_hostbuffer_impl
artemisTurintech Jul 30, 2026
1842d16
Pass track_memory through ocl create_hostbuffer
artemisTurintech Jul 30, 2026
10d4a69
Accept track_memory in create_hostbuffer_impl
artemisTurintech Jul 30, 2026
7289169
Track mmap host memory when requested
artemisTurintech Jul 30, 2026
98fe4e7
Match create_hostbuffer signature in ze_engine
artemisTurintech Jul 30, 2026
2ca6957
Match create_hostbuffer signature in ze_engine
artemisTurintech Jul 30, 2026
77b5549
Match create_hostbuffer signature in sycl_engine
artemisTurintech Jul 30, 2026
4a3176c
Match create_hostbuffer signature in sycl_engine
artemisTurintech Jul 30, 2026
11bc1ad
Track file-mapped host memory in remote tensor
artemisTurintech Jul 30, 2026
37e8f2e
Move file tensor test next to CPU-memory test
artemisTurintech Jul 30, 2026
43a0a0b
Add OCL-only file-mmap remote tensor inference test
artemisTurintech Jul 30, 2026
d7be9ad
still some problem with tests
michal-miotk Jul 31, 2026
57a7348
fix clang
michal-miotk Jul 31, 2026
0ace949
fix clang
michal-miotk Jul 31, 2026
d76930f
fix test
michal-miotk Aug 5, 2026
e0f388d
wip
michal-miotk Aug 5, 2026
4b8a409
added more requirements, delete one comment
michal-miotk Aug 6, 2026
529f35e
wip
michal-miotk Aug 6, 2026
6a60247
wip
michal-miotk Aug 6, 2026
c840721
more test cases
michal-miotk Aug 6, 2026
2ce2993
fix test on windows
michal-miotk Aug 10, 2026
ad8bd7c
added rw to mmap
michal-miotk Aug 10, 2026
b519c40
tests rw
michal-miotk Aug 10, 2026
849eba8
doc update
michal-miotk Aug 10, 2026
0e45da9
apply copilot insights and more
michal-miotk Aug 10, 2026
e1ea02f
Merge branch 'master' into tensor_file
michal-miotk Aug 10, 2026
b388ab7
fix comments of copilot
michal-miotk Aug 10, 2026
49ecdf3
apply some of reviewer comments
michal-miotk Aug 10, 2026
a0930ec
Merge branch 'master' into tensor_file
michal-miotk Aug 10, 2026
f12d420
change api
michal-miotk Aug 11, 2026
ff2d11a
fix compilation
michal-miotk Aug 11, 2026
aa3bc56
Revert "apply some of reviewer comments"
michal-miotk Aug 11, 2026
569801b
apply reviewer comment
michal-miotk Aug 11, 2026
ea39144
apply reviewer comments
michal-miotk Aug 12, 2026
7c9af31
added missing docs for cpu pointer (scope of PR 36539)
michal-miotk Aug 12, 2026
adcecaf
edit test
michal-miotk Aug 12, 2026
623d9b5
Merge branch 'master' into tensor_file
michal-miotk Aug 12, 2026
57d3976
delete unnecessary flag - FILE_MAP_WRITE is read write access
michal-miotk Aug 13, 2026
7ad7ea9
better comment, better mode
michal-miotk Aug 13, 2026
21a8abe
enable file share delete for rw variant
michal-miotk Aug 13, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ int main() {
//! [wrap_cpu_pointer]
}

{
//! [wrap_file]
// The plugin memory-maps the file and keeps the mapping alive for the tensor lifetime,
// so the file must not be modified until the returned tensor is destroyed.
ov::intel_gpu::FileDescriptor file_descriptor{"input.bin",
/*offset_in_bytes=*/0,
ov::intel_gpu::FileAccess::READ};
auto remote_tensor = gpu_context.create_tensor(in_element_type, in_shape, file_descriptor);
//! [wrap_file]
}

{
//! [wrap_cl_mem]
cl_mem shared_buffer = allocate_cl_mem(input_size);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,19 @@ For more details, see the code snippets below:
:language: cpp
:fragment: [wrap_usm_pointer]

.. tab-item:: CPU pointer
:sync: cpu-pointer

Use this overload when your application owns a CPU virtual address, for example memory
allocated with ``ov::util::aligned_alloc`` or memory mapped from a file. On the OpenCL
backend, the pointer address and allocation size must be aligned to
``ov::intel_gpu::cacheline_size``. The memory must remain valid for the whole lifetime of
the created remote tensor.

.. doxygensnippet:: docs/articles_en/assets/snippets/gpu/remote_objects_creation.cpp
:language: cpp
:fragment: [wrap_cpu_pointer]

.. tab-item:: cl_mem
:sync: cl-mem

Expand Down Expand Up @@ -267,6 +280,20 @@ For more details, see the code snippets below:
The ``shape`` and ``element type`` must describe the same memory layout as the external buffer.
The handle must remain valid for the whole lifetime of the created remote tensor.

.. tab-item:: file
:sync: file

Use this overload to wrap tensor data stored in a file. The access mode is declared in the
descriptor: ``FileAccess::READ`` maps the file read-only and may only be used as an inference
input, while ``FileAccess::READ_WRITE`` requires a writable file, may be used as an inference
output, and makes changes done through the tensor visible in the file. The plugin keeps the
mapping alive for the whole lifetime of the created remote tensor, so the file must not
otherwise be modified until the tensor is destroyed.

.. doxygensnippet:: docs/articles_en/assets/snippets/gpu/remote_objects_creation.cpp
:language: cpp
:fragment: [wrap_file]

.. tab-item:: biplanar NV12 surface
:sync: biplanar-nv12-surface

Expand Down
18 changes: 17 additions & 1 deletion src/common/util/include/openvino/util/mmap_object.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ int64_t get_system_page_size();
*/
inline constexpr auto auto_size = std::numeric_limits<size_t>::max();

/**
* @brief Access mode of a memory mapping.
*/
enum class MmapMode {
READ, //!< Read-only mapping.
READ_WRITE //!< Read-write mapping, modifications are written back to the file.
};

/**
* @brief Id reported by mappings whose content is mutable, so they must never be substituted for one another.
*/
inline constexpr uint64_t no_mapping_id = 0;
Comment thread
t-jankowski marked this conversation as resolved.

/**
* @brief This class represents a mapped memory.
* Instead of reading files, we can map the memory via mmap for Linux or MapViewOfFile for Windows.
Expand Down Expand Up @@ -73,12 +86,15 @@ class MappedMemory {
* @param no_placeholder When true, skip the Windows 10+ placeholder/VEH mechanism and use the legacy
* single-call MapViewOfFile path instead. This guarantees a uniform AllocationBase
* across the whole mapping, required for NPU zero-copy blob import. On Linux ignored.
* @param mode Access mode of the mapping. A read_write mapping requires the file to be writable and reports
* no_mapping_id, because get_id() marks an immutable data source that consumers may share.
* @return MappedMemory shared ptr object which keep mmaped memory and control the lifetime.
*/
std::shared_ptr<ov::MappedMemory> load_mmap_object(const std::filesystem::path& path,
size_t offset = 0,
size_t size = auto_size,
bool no_placeholder = false);
bool no_placeholder = false,
MmapMode mode = MmapMode::READ);

/**
* @brief Returns mapped memory for a file from provided file handle (cross-platform).
Expand Down
25 changes: 15 additions & 10 deletions src/common/util/src/os/lin/lin_mmap_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,18 +141,18 @@ class MapHolder final : public MappedMemory {
public:
MapHolder() = default;

void set(const std::filesystem::path& path, const size_t offset, const size_t size) {
int mode = O_RDONLY;
void set(const std::filesystem::path& path, const size_t offset, const size_t size, const MmapMode mmap_mode) {
int mode = (mmap_mode == MmapMode::READ_WRITE) ? O_RDWR : O_RDONLY;
int fd = open(path.c_str(), mode);
if (fd == -1) {
throw std::runtime_error("Can not open file " + util::path_to_string(path) +
" for mapping. Ensure that file exists and has appropriate permissions.");
}
set_from_fd(fd, offset, size);
m_id = util::get_id_for_file(path, offset, size);
set_from_fd(fd, offset, size, mmap_mode);
m_id = (mmap_mode == MmapMode::READ_WRITE) ? no_mapping_id : util::get_id_for_file(path, offset, size);
Comment thread
t-jankowski marked this conversation as resolved.
}

void set_from_fd(const int fd, const size_t offset, const size_t size) {
void set_from_fd(const int fd, const size_t offset, const size_t size, const MmapMode mmap_mode = MmapMode::READ) {
m_handle = HandleHolder(fd);

struct stat sb = {};
Expand All @@ -166,17 +166,21 @@ class MapHolder final : public MappedMemory {
}

if (m_size > 0) {
const auto prot = (mmap_mode == MmapMode::READ_WRITE) ? (PROT_READ | PROT_WRITE) : PROT_READ;
const auto& [aligned_offset, length, gap] = util::make_mmap_region(offset, m_size);
m_mapped_view_size = length;
m_mapped_view = mmap(nullptr, length, PROT_READ, MAP_SHARED, fd, aligned_offset);
m_mapped_view = mmap(nullptr, length, prot, MAP_SHARED, fd, aligned_offset);
if (m_mapped_view == MAP_FAILED) {
throw std::runtime_error("Can not create file mapping for " + std::to_string(fd) +
", err=" + std::strerror(errno));
}
m_data = static_cast<char*>(m_mapped_view) + gap;
}
m_id =
util::u64_hash_combine(static_cast<uint64_t>(sb.st_ino), {static_cast<uint64_t>(sb.st_dev), offset, size});
// A read-write mapping is not an immutable data source, so it must not be shared through id-based caches.
m_id = (mmap_mode == MmapMode::READ_WRITE)
? no_mapping_id
: util::u64_hash_combine(static_cast<uint64_t>(sb.st_ino),
{static_cast<uint64_t>(sb.st_dev), offset, size});
}

uint64_t get_id() const noexcept override {
Expand Down Expand Up @@ -231,9 +235,10 @@ class MapHolder final : public MappedMemory {
std::shared_ptr<MappedMemory> load_mmap_object(const std::filesystem::path& path,
size_t offset,
size_t size,
bool /* no_placeholder */) {
bool /* no_placeholder */,
MmapMode mode) {
auto holder = std::make_shared<MapHolder>();
holder->set(path, offset, size);
holder->set(path, offset, size, mode);
return holder;
}

Expand Down
48 changes: 31 additions & 17 deletions src/common/util/src/os/win/win_mmap_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,11 @@ class MapHolder : public ov::MappedMemory {
MapHolder() = default;
~MapHolder() override;

void set(const std::filesystem::path& path, size_t offset, size_t size, bool no_placeholder = false);
void set(const std::filesystem::path& path,
size_t offset,
size_t size,
bool no_placeholder = false,
MmapMode mode = MmapMode::READ);
void set_from_handle(FileHandle handle, size_t offset, size_t size);
bool try_remap_slot(uintptr_t fault_addr);

Expand Down Expand Up @@ -334,15 +338,15 @@ class MapHolder : public ov::MappedMemory {
void set_id(HANDLE h, size_t offset, size_t size);

/** @brief Core setup shared by set() and set_from_handle(). */
void setup(HANDLE file_handle, size_t offset, size_t size, bool no_placeholder);
void setup(HANDLE file_handle, size_t offset, size_t size, bool no_placeholder, MmapMode mode);

/** @brief Try to establish the placeholder mapping.
* Returns true on success; caller falls back to legacy path on false.
*/
bool try_placeholder_setup(size_t aligned_offset, size_t head_pad, size_t total_va_size, size_t file_size);

/** @brief Legacy single-call MapViewOfFile path (no partial-release support). */
void legacy_setup(size_t aligned_offset, size_t head_pad, size_t size);
void legacy_setup(size_t aligned_offset, size_t head_pad, size_t size, MmapMode mode);

/**
* @brief Computes the clamped, gran-aligned VA range to evict.
Expand Down Expand Up @@ -614,9 +618,10 @@ bool MapHolder::try_placeholder_setup(size_t aligned_offset, size_t head_pad, si
return true;
}

void MapHolder::legacy_setup(size_t aligned_offset, size_t head_pad, size_t size) {
void MapHolder::legacy_setup(size_t aligned_offset, size_t head_pad, size_t size, MmapMode mode) {
const DWORD access = (mode == MmapMode::READ_WRITE) ? (FILE_MAP_READ | FILE_MAP_WRITE) : FILE_MAP_READ;
if (auto view = ::MapViewOfFile(m_handle.get(),
FILE_MAP_READ,
access,
static_cast<DWORD>(aligned_offset >> 32),
static_cast<DWORD>(aligned_offset & 0xFFFFFFFF),
head_pad + size)) {
Expand All @@ -627,7 +632,7 @@ void MapHolder::legacy_setup(size_t aligned_offset, size_t head_pad, size_t size
}
}

void MapHolder::setup(HANDLE file_handle, size_t offset, size_t size, bool no_placeholder) {
void MapHolder::setup(HANDLE file_handle, size_t offset, size_t size, bool no_placeholder, MmapMode mode) {
LARGE_INTEGER file_size_li{};
if (!::GetFileSizeEx(file_handle, &file_size_li)) {
throw std::runtime_error{"GetFileSizeEx failed: " + std::to_string(::GetLastError())};
Expand All @@ -646,28 +651,36 @@ void MapHolder::setup(HANDLE file_handle, size_t offset, size_t size, bool no_pl
const size_t total_va_size = util::align_size_up(r_length, gran);

set_id(file_handle, offset, size);
if (mode == MmapMode::READ_WRITE) {
// A read-write mapping is not an immutable data source, so it must not be shared through id-based caches.
m_id = no_mapping_id;
}

if (m_size == 0) {
return;
}

// Create a read-only file-mapping object for the whole file.
m_handle = HandleHolder{::CreateFileMappingW(file_handle, nullptr, PAGE_READONLY, 0, 0, nullptr)};
const DWORD protect = (mode == MmapMode::READ_WRITE) ? PAGE_READWRITE : PAGE_READONLY;
m_handle = HandleHolder{::CreateFileMappingW(file_handle, nullptr, protect, 0, 0, nullptr)};
if (!m_handle.valid()) {
throw std::runtime_error{"CreateFileMappingW failed: " + std::to_string(::GetLastError())};
}

// When no_placeholder is set, skip the placeholder/VEH path to guarantee a single uniform AllocationBase
// (required for NPU zero-copy blob import). Otherwise prefer placeholder for RSS reduction.
if (no_placeholder || !try_placeholder_setup(m_aligned_offset, head_pad, total_va_size, file_size)) {
legacy_setup(m_aligned_offset, head_pad, m_size);
// Read-write mappings always take the legacy path: the VEH only remaps on read faults, so an evicted
// granule hit by a write would fault indefinitely.
if (no_placeholder || mode == MmapMode::READ_WRITE ||
!try_placeholder_setup(m_aligned_offset, head_pad, total_va_size, file_size)) {
legacy_setup(m_aligned_offset, head_pad, m_size, mode);
}
}

void MapHolder::set(const std::filesystem::path& path, size_t offset, size_t size, bool no_placeholder) {
void MapHolder::set(const std::filesystem::path& path, size_t offset, size_t size, bool no_placeholder, MmapMode mode) {
const bool writable = mode == MmapMode::READ_WRITE;
auto fh = ::CreateFileW(path.c_str(),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_DELETE,
writable ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ,
writable ? (FILE_SHARE_READ | FILE_SHARE_WRITE) : (FILE_SHARE_READ | FILE_SHARE_DELETE),
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS,
Expand All @@ -678,7 +691,7 @@ void MapHolder::set(const std::filesystem::path& path, size_t offset, size_t siz
}

HandleHolder fh_holder{fh};
setup(fh, offset, size, no_placeholder);
setup(fh, offset, size, no_placeholder, mode);
// Keep the file handle alive so the section object can always resolve page faults
// back to the original file data, even if the caller deletes or renames the file.
// FILE_SHARE_DELETE allows std::filesystem::remove() to succeed while the mapping is alive.
Expand All @@ -702,7 +715,7 @@ void MapHolder::set_from_handle(FileHandle handle, size_t offset, size_t size) {
throw std::runtime_error{"DuplicateHandle failed: " + std::to_string(::GetLastError())};
}
HandleHolder owned{dup};
setup(owned.get(), offset, size, false);
setup(owned.get(), offset, size, false, MmapMode::READ);
// owned goes out of scope here: file handle closed.
// m_handle (section object) keeps the file data accessible independently.
}
Expand Down Expand Up @@ -947,9 +960,10 @@ void MapHolder::hint_evict(size_t offset, size_t size) noexcept {
std::shared_ptr<ov::MappedMemory> load_mmap_object(const std::filesystem::path& path,
size_t offset,
size_t size,
bool no_placeholder) {
bool no_placeholder,
MmapMode mode) {
auto holder = std::make_shared<MapHolder>();
holder->set(path, offset, size, no_placeholder);
holder->set(path, offset, size, no_placeholder, mode);
return holder;
}

Expand Down
54 changes: 54 additions & 0 deletions src/core/tests/mmap_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,60 @@ INSTANTIATE_TEST_SUITE_P(MappedMemory,
::testing::ValuesIn(std::vector<bool>{true, false})),
RangedMappingTest::test_name);

class ReadWriteMappingTest : public ::testing::Test {
protected:
std::filesystem::path m_file_path;
std::vector<uint8_t> m_content;
static constexpr size_t k_file_size = 128 * 1024;

void SetUp() override {
m_content = utils::make_modulo_sequence_pattern(k_file_size);
m_file_path = utils::generateTestFilePrefix() + "_rw_mapping";
ov::util::save_binary(m_file_path, m_content.data(), m_content.size());
}

void TearDown() override {
std::filesystem::remove(m_file_path);
}

std::vector<uint8_t> read_file() const {
std::vector<uint8_t> data(static_cast<size_t>(std::filesystem::file_size(m_file_path)));
std::ifstream is(m_file_path, std::ios::binary);
is.read(reinterpret_cast<char*>(data.data()), static_cast<std::streamsize>(data.size()));
return data;
}
};

TEST_F(ReadWriteMappingTest, writes_at_offset_leave_other_bytes_intact) {
constexpr size_t k_offset = 64 * 1024;
constexpr size_t k_size = 512;

auto expected = m_content;
std::fill_n(expected.begin() + k_offset, k_size, uint8_t{0x5A});
ASSERT_NE(expected, m_content);

{
auto mm = load_mmap_object(m_file_path, k_offset, k_size, false, MmapMode::READ_WRITE);
std::fill_n(reinterpret_cast<uint8_t*>(mm->data()), k_size, uint8_t{0x5A});
}

EXPECT_THAT(read_file(), ElementsAreArray(expected));
}

TEST_F(ReadWriteMappingTest, read_write_mappings_report_no_mapping_id) {
auto rw_whole = load_mmap_object(m_file_path, 0, auto_size, false, MmapMode::READ_WRITE);
auto rw_part = load_mmap_object(m_file_path, 128, 256, false, MmapMode::READ_WRITE);
auto ro = load_mmap_object(m_file_path);

ASSERT_NE(rw_whole, nullptr);
ASSERT_NE(rw_part, nullptr);
ASSERT_NE(ro, nullptr);

EXPECT_EQ(rw_whole->get_id(), no_mapping_id);
EXPECT_EQ(rw_part->get_id(), no_mapping_id);
EXPECT_NE(ro->get_id(), no_mapping_id);
}

class HintEvictTest : public ::testing::Test {
protected:
std::filesystem::path m_file_path;
Expand Down
21 changes: 20 additions & 1 deletion src/inference/include/openvino/runtime/intel_gpu/ocl/ocl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
*/
#pragma once

#include <memory>
#include <string>

#include "openvino/runtime/core.hpp"
Expand Down Expand Up @@ -43,6 +42,7 @@ using gpu_handle_param = void*;

using SharedBufferHandle = ov::intel_gpu::SharedBufferHandle;
using VirtualAddressMemory = ov::intel_gpu::VirtualAddressMemory;
using FileDescriptor = ov::intel_gpu::FileDescriptor;

/**
* @brief This class represents an abstraction for GPU plugin remote tensor
Expand Down Expand Up @@ -346,6 +346,25 @@ class ClContext : public RemoteContext {
return create_tensor(type, shape, params).as<ClBufferTensor>();
}

/**
* @brief This function is used to obtain a remote tensor object from a file.
* The plugin memory-maps the file and keeps the mapping alive for the whole tensor lifetime,
* so the file must not be modified until the returned tensor is destroyed.
* @param type Tensor element type
* @param shape Tensor shape
* @param file_descriptor Descriptor with the path, offset and access mode of the file containing tensor data.
* The offset must be a multiple of the system memory mapping alignment: the page size on Linux
* (typically 4 KiB) and the allocation granularity on Windows (typically 64 KiB).
* FileAccess::READ_WRITE additionally requires the file to be writable by the calling process
* and makes the tensor writes visible in the file.
* @return A remote tensor instance
*/
ClBufferTensor create_tensor(const element::Type type, const Shape& shape, const FileDescriptor& file_descriptor) {
AnyMap params = {{ov::intel_gpu::shared_mem_type.name(), ov::intel_gpu::SharedMemType::MMAPED_FILE},
{ov::intel_gpu::file_descriptor.name(), file_descriptor}};
return create_tensor(type, shape, params).as<ClBufferTensor>();
}

/**
* @brief This function is used to obtain remote tensor object from user-supplied USM pointer
* @param type Tensor element type
Expand Down
Loading
Loading