Skip to content

Commit 6c189f2

Browse files
committed
fixes
1 parent 5677bb3 commit 6c189f2

5 files changed

Lines changed: 32 additions & 73 deletions

File tree

src/common/util/src/memory.cpp

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,13 @@
99
#include <thread>
1010
#include <vector>
1111

12+
#include "memory_prefetch.hpp"
1213
#include "openvino/util/common_util.hpp"
1314
#include "openvino/util/mmap_object.hpp"
1415

1516
namespace ov::util {
1617
void populate_pages(void* ptr, size_t size, size_t num_threads) noexcept;
1718

18-
namespace {
19-
20-
// Touches one byte per page over [m_begin, m_end) to force the pages resident. The volatile
21-
// accumulator keeps the compiler from eliminating the read loop.
22-
struct PageToucher {
23-
const uint8_t* m_begin;
24-
const uint8_t* m_end;
25-
const size_t m_page_size;
26-
27-
void operator()() const noexcept {
28-
volatile uint8_t local = 0;
29-
for (auto begin = m_begin; begin < m_end; begin += m_page_size) {
30-
local += *begin;
31-
}
32-
}
33-
};
34-
35-
} // namespace
36-
3719
void populate_pages(void* ptr, size_t size, size_t num_threads) noexcept {
3820
const auto page_size = static_cast<size_t>(get_system_page_size());
3921
const auto chunk_size = std::max<size_t>(align_size_up(size / num_threads, page_size), one_mib);

src/common/util/src/memory_prefetch.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,21 @@
1717

1818
namespace ov::util {
1919

20+
// Touches one byte per page over [m_begin, m_end) to force the pages resident. The volatile
21+
// accumulator keeps the compiler from eliminating the read loop.
22+
struct PageToucher {
23+
const uint8_t* m_begin;
24+
const uint8_t* m_end;
25+
const size_t m_page_size;
26+
27+
void operator()() const noexcept {
28+
volatile uint8_t local = 0;
29+
for (auto begin = m_begin; begin < m_end; begin += m_page_size) {
30+
local += *begin;
31+
}
32+
}
33+
};
34+
2035
class PrefetchToken;
2136

2237
/**

src/common/util/src/os/lin/lin_memory.cpp

Lines changed: 16 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
#include <cstddef>
1111
#include <cstdint>
1212
#include <cstdlib>
13-
#include <cstring>
1413
#include <functional>
1514
#include <future>
1615
#include <list>
@@ -34,22 +33,6 @@ void madvise_hint(void* ptr, size_t size) noexcept {
3433
madvise(ptr, size, MADV_WILLNEED);
3534
}
3635

37-
// Touches one byte per page over [m_begin, m_end) to force the pages resident. The volatile
38-
// accumulator keeps the compiler from eliminating the read loop.
39-
struct PageToucher {
40-
const uint8_t* m_begin;
41-
const uint8_t* m_end;
42-
const size_t m_page_size;
43-
44-
void operator()() const noexcept {
45-
volatile uint8_t local = 0;
46-
for (auto begin = m_begin; begin < m_end; begin += m_page_size) {
47-
local += *begin;
48-
}
49-
}
50-
};
51-
52-
// Thread-safe queue of population jobs. Owns only the queueing/notification concern.
5336
class TaskQueue {
5437
public:
5538
void push(std::list<std::function<void()>>&& batch) noexcept {
@@ -89,8 +72,6 @@ class TaskQueue {
8972
bool m_stop = false;
9073
};
9174

92-
// Process-wide, bounded pool of worker threads that drain a shared TaskQueue. Keeping the worker
93-
// count bounded means repeated prefetch calls reuse the same threads instead of spawning new ones.
9475
class ThreadPool {
9576
public:
9677
static ThreadPool& instance() {
@@ -101,9 +82,6 @@ class ThreadPool {
10182
ThreadPool(const ThreadPool&) = delete;
10283
ThreadPool& operator=(const ThreadPool&) = delete;
10384

104-
// Enqueueing is all-or-nothing: every throwing operation (task/future creation) happens on
105-
// local state first, and the finished batch is spliced into the queue with a non-throwing
106-
// splice. If preparation throws, nothing is enqueued and no job runs.
10785
std::vector<std::future<void>> submit(std::vector<std::function<void()>>&& jobs) {
10886
std::vector<std::future<void>> futures;
10987
futures.reserve(jobs.size());
@@ -151,19 +129,23 @@ class ThreadPool {
151129
std::vector<std::thread> m_workers;
152130
};
153131

154-
// Splits [ptr, ptr + size) into num_threads page-toucher jobs and submits them to the shared pool.
155-
std::vector<std::future<void>> submit_page_toucher_tasks(void* ptr, size_t size, size_t num_threads) {
156-
const auto page_size = static_cast<size_t>(get_system_page_size());
157-
const auto chunk_size =
158-
std::max<size_t>(align_size_up(size / num_threads, page_size), default_parallel_io_min_chunk);
132+
std::vector<std::future<void>> submit_page_toucher_tasks(void* ptr, size_t size, size_t num_threads) noexcept {
133+
try {
134+
const auto page_size = static_cast<size_t>(get_system_page_size());
135+
const auto chunk_size =
136+
std::max<size_t>(align_size_up(size / num_threads, page_size), default_parallel_io_min_chunk);
159137

160-
std::vector<std::function<void()>> jobs;
161-
jobs.reserve(ceil_div(size, chunk_size));
138+
std::vector<std::function<void()>> jobs;
139+
jobs.reserve(ceil_div(size, chunk_size));
162140

163-
for (auto first = reinterpret_cast<const uint8_t*>(ptr), last = first + size; first < last; first += chunk_size) {
164-
jobs.emplace_back(PageToucher{first, std::min(first + chunk_size, last), page_size});
141+
for (auto first = reinterpret_cast<const uint8_t*>(ptr), last = first + size; first < last;
142+
first += chunk_size) {
143+
jobs.emplace_back(PageToucher{first, std::min(first + chunk_size, last), page_size});
144+
}
145+
return ThreadPool::instance().submit(std::move(jobs));
146+
} catch (...) {
147+
return {};
165148
}
166-
return ThreadPool::instance().submit(std::move(jobs));
167149
}
168150
} // namespace
169151

@@ -215,29 +197,14 @@ void vm_release(void* ptr, size_t size) noexcept {
215197

216198
void vm_prefetch(void* ptr, size_t size, size_t num_threads) noexcept {
217199
if (num_threads == 0) {
218-
// Advisory-only: let the OS decide, no page touching.
219200
madvise_hint(ptr, size);
220201
return;
221202
}
222-
// Parallel synchronous touch, blocking until every page is resident. Must not run on a pool
223-
// worker thread (it would deadlock waiting on the pool). Prefetching is best-effort, so on
224-
// allocation failure fall back to an advisory hint rather than escaping this noexcept function.
225-
try {
226-
PrefetchToken(submit_page_toucher_tasks(ptr, size, num_threads)).wait();
227-
} catch (...) {
228-
madvise_hint(ptr, size);
229-
}
203+
PrefetchToken(submit_page_toucher_tasks(ptr, size, num_threads)).wait();
230204
}
231205

232206
PrefetchToken vm_prefetch_async(void* ptr, size_t size) noexcept {
233-
// Ownership of the futures is transferred to the token; it waits on them on destruction or via
234-
// an explicit wait(). If submission fails, fall back to an advisory hint and return an empty token.
235-
try {
236-
return PrefetchToken(submit_page_toucher_tasks(ptr, size, prefetch_thread_count(size)));
237-
} catch (...) {
238-
madvise_hint(ptr, size);
239-
return PrefetchToken{};
240-
}
207+
return PrefetchToken(submit_page_toucher_tasks(ptr, size, prefetch_thread_count(size)));
241208
}
242209

243210
} // namespace ov::util

src/common/util/src/os/lin/lin_mmap_object.cpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,6 @@ class MapHolder final : public MappedMemory {
198198

199199
void hint_prefetch_async(size_t offset, size_t size) override {
200200
if (const auto plan = util::make_prefetch_plan(m_data, m_size, offset, size); plan.m_aligned_size) {
201-
// Adopt the token's tasks into m_pending_prefetch within this same call, before
202-
// returning, so ~MapHolder() always joins them before munmap regardless of what the
203-
// caller does next. The token is never handed back, so there is no window where the
204-
// tasks' lifetime is decoupled from this object's.
205201
auto token = util::vm_prefetch_async(reinterpret_cast<void*>(plan.m_address), plan.m_aligned_size);
206202
adopt_pending_prefetch(token.detach());
207203
}

src/common/util/src/os/win/win_memory.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ void vm_prefetch(void* ptr, size_t size, size_t num_threads) noexcept {
7171
}
7272

7373
PrefetchToken vm_prefetch_async(void* ptr, size_t size) noexcept {
74-
// CVS-186579: no background work is started on Windows yet; mirrors the vm_prefetch() stub.
7574
return {};
7675
}
7776

0 commit comments

Comments
 (0)