Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 12 additions & 0 deletions backends/xnnpack/runtime/XNNPACKBackend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ class XnnpackBackend final
return first_err;
}

public:
/** See xnnpack::get_packed_cache_report(). */
xnnpack::PackedCacheReport packed_cache_report() const {
return options_.weights_cache_manager().report();
}

private:
mutable xnnpack::XnnpackBackendOptions options_;

Expand All @@ -272,5 +278,11 @@ Backend backend{xnnpack::xnnpack_backend_key, &backend_instance};
static auto success_with_compiler = register_backend(backend);
} // namespace

namespace xnnpack {
PackedCacheReport get_packed_cache_report() {
return backend_instance.packed_cache_report();
}
} // namespace xnnpack

} // namespace backends
} // namespace executorch
114 changes: 114 additions & 0 deletions backends/xnnpack/runtime/XNNPACKBackend.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
#pragma once

#include <array>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

namespace executorch::backends::xnnpack {
/// The key for the backend. This is used to register the backend, check
/// availability, and get/set options.
Expand Down Expand Up @@ -31,6 +37,7 @@
// @lint-ignore CLANGTIDY facebook-hte-CArray
const char save_weight_cache_on_disk_option_key[] = "save_weight_cache_on_disk";


/// Workspace sharing mode. This is a backend option that can be set via the
/// set_option API to control memory sharing between CALL_DELEGATE instances.
/// This is useful for reducing memory consumption.
Expand Down Expand Up @@ -61,4 +68,111 @@
// maximum enum value.
Count,
};

/// Outcome of opening the packed-weight cache file.
enum class PackedCacheState : int32_t {
/// No cache path configured — the caller never opted in.
Disabled = 0,
/// The cache file opened. Does NOT imply zero heap; see PackedCacheStats.
FileBacked = 1,
/// A path was configured but the file could not be used.
HeapFallback = 2,
};

/** Why an individual allocation was served from heap. */
enum class PackedCacheHeapReason : int32_t {
None = 0,
/// The instance has no cache path: it never opted into file backing, so
/// heap is the intended behaviour rather than a fallback. Bucketed
/// separately and excluded from heap_bytes — a process that mixes an
/// opted-in model with a non-opted-in one would otherwise report the
/// latter's packed weights as if the former had fallen back.
NotOptedIn = 1,
/// Unnamed constant — can never be reloaded by name. By design.
UnnamedConstant = 2,
/// Incidental re-pack after a successful load. By design *if* the loaded
/// cache is complete; a large volume here means it was not.
RepackAfterLoad = 3,
/// No usable file descriptor at allocation time.
NoFileBacking = 4,
/// ftruncate() to extend the file failed.
GrowFailed = 5,
/// mmap() of the grown region failed.
MmapFailed = 6,
/// Not a reason; bounds the per-reason counters. Matches the
/// WorkspaceSharingMode convention in this header.
Count,
};

/** Which step failed when a configured path still ended up on heap. */
enum class PackedCacheFailure : int32_t {
None = 0,
OpenFailed = 1,
TruncateFailed = 2,
GrowFailed = 3,
MmapFailed = 4,
};

/**
* Per-cache counters. `heap_bytes` against `mapped_bytes` is the signal;
* `state` alone calls a partially-loaded cache healthy.
*/
struct PackedCacheStats {
PackedCacheState state{PackedCacheState::Disabled};
PackedCacheFailure failure{PackedCacheFailure::None};
int32_t last_errno{0};
/// Cache file size as of the last successful save.
int64_t file_bytes{0};
/// Packed bytes served from heap when the file was supposed to serve them.
/// Excludes NotOptedIn, so this is only ever "bytes that should have been
/// file-backed and were not".
int64_t heap_bytes{0};
/// Packed bytes served from the mmap'd file (clean, file-backed).
int64_t mapped_bytes{0};
/// Reason accounting for the largest share of heap_bytes. On the aggregate
/// this is the argmax over per-reason bytes summed across caches, not the
/// local reason of whichever cache happened to allocate the most.
PackedCacheHeapReason heap_reason{PackedCacheHeapReason::None};
/// Heap bytes split by reason, so callers can sum per reason rather than
/// per cache. Index with PackedCacheHeapReason. Excludes nothing — the
/// NotOptedIn slot is populated here but omitted from `heap_bytes`.
std::array<int64_t, static_cast<std::size_t>(PackedCacheHeapReason::Count)>
heap_bytes_by_reason{};
};

/** One live cache instance and its own counters. */
struct PackedCacheEntry {
/// Cache file path. Empty for the shared heap-only instance handed to
/// callers that never configured one.
std::string path;
PackedCacheStats stats;
};

/**
* Aggregate plus the per-instance breakdown behind it.
*
* Both come from one pass, so the summary and the detail always describe the
* same instant. The breakdown exists because the aggregate alone cannot be
* attributed: a process running several models folds them into one number, so
* a fallback in one model is indistinguishable from a fallback in another.
* The manager already keys caches by path — this stops discarding that.
*
* Takes no per-instance lock: the counters are atomics, so this never waits
* on a model compile.
*/
struct PackedCacheReport {
/// Summed counters. `failure` / `last_errno` are left unset here; read them
/// from the `dominant_fallback` entry so they stay tied to one cache.
PackedCacheStats aggregate;
/// Sorted by path, so repeated calls agree regardless of map iteration
/// order.
std::vector<PackedCacheEntry> per_cache;
/// Index into `per_cache` of the cache that best explains a fallback: the
/// largest heap contributor, or if none allocated, the first cache in
/// HeapFallback. -1 when nothing fell back.
int32_t dominant_fallback{-1};
};

PackedCacheReport get_packed_cache_report();

} // namespace executorch::backends::xnnpack
Loading
Loading