forked from iree-org/iree
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexecutable_cache.h
145 lines (126 loc) · 6.58 KB
/
executable_cache.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef THIRD_PARTY_MLIR_EDGE_IREE_HAL_EXECUTABLE_CACHE_H_
#define THIRD_PARTY_MLIR_EDGE_IREE_HAL_EXECUTABLE_CACHE_H_
#include "third_party/mlir_edge/iree/base/bitfield.h"
#include "third_party/mlir_edge/iree/base/ref_ptr.h"
#include "third_party/mlir_edge/iree/base/status.h"
#include "third_party/mlir_edge/iree/base/wait_handle.h"
#include "third_party/mlir_edge/iree/hal/executable.h"
#include "third_party/mlir_edge/iree/hal/executable_format.h"
#include "third_party/mlir_edge/iree/hal/executable_spec.h"
namespace iree {
namespace hal {
// Defines how the executable cache performs preparation.
enum class ExecutableCachingMode : uint32_t {
// Allows the cache to reference the provided executable_data after it has
// prepared the executable. Callers must ensure the data remains valid for the
// lifetime of the cache. If memory mapping constant executable data from
// disk this can be used to avoid copies.
kAliasProvidedData = 1 << 0,
// Allows the prepared executable to be cached persistently (on disk/etc).
// Enable for any executable that is likely to be used in future runs.
// Note that not all caches support persistent serialization and this is just
// a hint.
kAllowPersistentCaching = 1 << 1,
// Allows the cache to optimize the executable as much as it can.
// This may cause preparation to take significantly longer while (hopefully)
// improving runtime performance. Avoid for one-shot executables.
kAllowOptimization = 1 << 2,
// Enables Executable debugging methods if supported by the device and
// executable. This may disable certain optimizations or retain additional
// data to allow disassembly, stepping, etc.
//
// Device must support the DeviceFeature::kDebugging feature and executables
// must support the ExecutableFeature::kDebugging feature.
kEnableDebugging = 1 << 3,
// Enables Executable coverage if supported by the device and executable.
// Depending on the optimization mode this may produce partial coverage
// results (for example, when certain source operations were optimized away).
//
// Device must support the DeviceFeature::kCoverage feature and executables
// must support the ExecutableFeature::kCoverage feature.
kEnableCoverage = 1 << 4,
// Enables Executable profiling if supported by the device and executable.
// Depending on the optimization mode this may produce partial profiling
// results. Profiling attribution (whether to the entire executable or
// specific operations) depends on the implementation.
//
// Device must support the DeviceFeature::kProfiling feature and executables
// must support the ExecutableFeature::kProfiling feature.
kEnableProfiling = 1 << 5,
// Default caching mode.
kDefault = kAllowPersistentCaching | kAllowOptimization,
};
IREE_BITFIELD(ExecutableCachingMode);
using ExecutableCachingModeBitfield = ExecutableCachingMode;
// A cache of prepared executables for a particular device.
// Caches may be shared across multiple devices from the same driver or specific
// to individual devices. Caches may persist prepared executables across process
// launches or reprepare them each run. Callers should assume that the cache is
// a no-op and the returned Executables only live for as long as the cache does.
//
// The term 'cache' here is rather optimistic - it's perfectly acceptable for
// implementations to not cache at all and return new Executables for each
// PrepareExecutable called (even for the same executable). Callers should
// expect such behavior and try to retain the results of the PrepareExecutable
// calls to reduce overhead in re-preparing executables.
//
// Thread-safe - multiple threads may prepare executables (including the *same*
// executable) simultaneously.
class ExecutableCache {
public:
virtual ~ExecutableCache();
// TODO(benvanik): status/queries (size, etc).
// TODO(b/137153339): serialization/deserialization.
// Returns true if the executable cache can prepare the given executable input
// format. Perparation may still fail if the particular version or features
// required by the executable are not supported.
virtual bool CanPrepareFormat(ExecutableFormat format) const = 0;
// Prepares an executable for use.
// The provided |spec| and |executable_data| will be used to either lookup a
// previously prepared executable in the cache or prepare a new one.
//
// Depending on the driver preparation may take a non-trivial amount of time
// (such as when JITing/etc). As the cache is internally synchronized callers
// can issue preparation requests from multiple threads - even for the same
// executables - and calls will block until preparation completes.
//
// When preparing a large number of executables it's recommended to use the
// PrepareExecutables method to batch and wait on the results.
virtual StatusOr<ref_ptr<Executable>> PrepareExecutable(
ExecutableCachingModeBitfield mode, const ExecutableSpec& spec) = 0;
// Prepares one or more executables asynchronously on a worker thread (maybe).
// When the WaitHandle is signaled successfully |out_executables| will contain
// one Executable for each ExecutableSpec provided in |specs|, in order.
// The backing memory of |out_executables| must remain valid until the
// WaitHandle resolves. Preparation errors will be returned on the WaitHandle.
// If more than one preparation errors occurs only one will be returned (from
// an undefined order).
//
// Note: not all implementations will actually perform preparation
// asynchronously. This method just allows drivers to do so as possible.
//
// If applications already have their own preparation threads it is better to
// use PrepareExecutable in a loop to avoid the creation of new threads.
virtual StatusOr<WaitHandle> PrepareExecutables(
ExecutableCachingModeBitfield mode,
absl::Span<const ExecutableSpec> specs,
absl::Span<ref_ptr<Executable>> out_executables);
protected:
ExecutableCache();
};
} // namespace hal
} // namespace iree
#endif // THIRD_PARTY_MLIR_EDGE_IREE_HAL_EXECUTABLE_CACHE_H_