LLVM 19.0.0git
ReleaseModeModelRunner.h
Go to the documentation of this file.
1//===- ReleaseModeModelRunner.h - Fast, precompiled model runner ---------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements a model runner wrapping an AOT compiled ML model.
10// Only inference is supported.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_ANALYSIS_RELEASEMODEMODELRUNNER_H
15#define LLVM_ANALYSIS_RELEASEMODEMODELRUNNER_H
16
21#include "llvm/Support/MD5.h"
22
23#include <memory>
24
25namespace llvm {
26
27/// ReleaseModeModelRunner - production mode implementation of the
28/// MLModelRunner. It uses an AOT-compiled SavedModel for efficient execution.
30 /// Feed and Fetch feature prefixes - i.e. a feature named "foo" will be
31 /// looked up as {FeedPrefix}_foo; and the output named "bar" will be looked
32 /// up as {FetchPrefix}_bar
35
36 /// ModelSelector is the name (recognized by the AOT-ed model) of a sub-model
37 /// to use. "" is allowed if the model doesn't support sub-models.
39
42 return *this;
43 }
46 return *this;
47 }
50 return *this;
51 }
52};
53
54template <class TGen>
56public:
57 /// FeatureNames' type should be an indexed collection of std::string, like
58 /// std::array or std::vector, that has a size() method.
59 template <class FType>
60 ReleaseModeModelRunner(LLVMContext &Ctx, const FType &InputSpec,
63 : MLModelRunner(Ctx, MLModelRunner::Kind::Release, InputSpec.size() + 1),
64 CompiledModel(std::make_unique<TGen>()) {
65 assert(CompiledModel && "The CompiledModel should be valid");
66 // Set up the model_selector past all the InputSpecs in all cases.
67 // - if the model doesn't have such a feature, but the user requested it,
68 // we report error. Same if the model supports it but the user didn't
69 // specify it
70 // - finally, we compute the MD5 hash of the user input and set the value
71 // of the model selector to {high, low}
72 bool InputIsPresent = true;
73 populateTensor(InputSpec.size(),
74 TensorSpec::createSpec<uint64_t>("model_selector", {2}),
75 Options.FeedPrefix, InputIsPresent);
76
77 // If we hit the "report an error" cases outlined above, continue with the
78 // set up in case there's some custom diagnostics handler installed and it
79 // doesn't promptly exit.
80 if (Options.ModelSelector.empty() && InputIsPresent)
82 "A model selector was not specified but the underlying model "
83 "requires selecting one because it exposes a model_selector input");
84 uint64_t High = 0;
85 uint64_t Low = 0;
86 if (!Options.ModelSelector.empty()) {
87 if (!InputIsPresent)
88 Ctx.emitError("A model selector was specified but the underlying model "
89 "does not expose a model_selector input");
90 const auto Hash = MD5::hash(arrayRefFromStringRef(Options.ModelSelector));
91 High = Hash.high();
92 Low = Hash.low();
93 }
94 getTensor<uint64_t>(InputSpec.size())[0] = High;
95 getTensor<uint64_t>(InputSpec.size())[1] = Low;
96 // At this point, the model selector is set up. If the user didn't provide
97 // one, but the model has a model_selector, it'll be set to (0, 0) which
98 // the composite model should treat as error as part of its implementation
99 // (but that should only matter if there is a custom handler that doesn't
100 // exit on error)
101 for (size_t I = 0; I < InputSpec.size(); ++I)
102 populateTensor(I, InputSpec[I], Options.FeedPrefix, InputIsPresent);
103
104 ResultIndex = CompiledModel->LookupResultIndex(Options.FetchPrefix.str() +
105 DecisionName.str());
106 assert(ResultIndex >= 0 && "Cannot find DecisionName in inlining model");
107 }
108
109 virtual ~ReleaseModeModelRunner() = default;
110
111 static bool classof(const MLModelRunner *R) {
112 return R->getKind() == MLModelRunner::Kind::Release;
113 }
114
115private:
116 // fetch the model-provided buffer for the given Spec, or let MLModelRunner
117 // create a scratch buffer. Indicate back to the caller if the model had that
118 // input in the first place.
119 void populateTensor(size_t Pos, const TensorSpec &Spec, StringRef Prefix,
120 bool &InputIsPresent) {
121 const int Index =
122 CompiledModel->LookupArgIndex((Prefix + Spec.name()).str());
123 void *Buffer = nullptr;
124 InputIsPresent = Index >= 0;
125 if (InputIsPresent)
126 Buffer = CompiledModel->arg_data(Index);
127 setUpBufferForTensor(Pos, Spec, Buffer);
128 }
129
130 void *evaluateUntyped() override {
131 CompiledModel->Run();
132 return CompiledModel->result_data(ResultIndex);
133 }
134
135 int32_t ResultIndex = -1;
136 std::unique_ptr<TGen> CompiledModel;
137};
138
139/// A mock class satisfying the interface expected by ReleaseModeModelRunner for
140/// its `TGen` parameter. Useful to avoid conditional compilation complexity, as
141/// a compile-time replacement for a real AOT-ed model.
143#define NOOP_MODEL_ERRMSG \
144 "The mock AOT-ed saved model is a compile-time stub and should not be " \
145 "called."
146
147public:
149 int LookupArgIndex(const std::string &) { llvm_unreachable(NOOP_MODEL_ERRMSG); }
154#undef NOOP_MODEL_ERRMSG
155};
156
157template <class T> bool isEmbeddedModelEvaluatorValid() { return true; }
158
160 return false;
161}
162} // namespace llvm
163
164#endif // LLVM_ANALYSIS_RELEASEMODEMODELRUNNER_H
static LVOptions Options
Definition: LVOptions.cpp:25
#define I(x, y, z)
Definition: MD5.cpp:58
uint64_t High
#define NOOP_MODEL_ERRMSG
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some functions that are useful when dealing with strings.
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
void emitError(uint64_t LocCookie, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
static MD5Result hash(ArrayRef< uint8_t > Data)
Computes the hash for a given bytes.
Definition: MD5.cpp:291
MLModelRunner interface: abstraction of a mechanism for evaluating a ML model.
Definition: MLModelRunner.h:26
void setUpBufferForTensor(size_t Index, const TensorSpec &Spec, void *Buffer)
Definition: MLModelRunner.h:63
LLVMContext & Ctx
Definition: MLModelRunner.h:72
A mock class satisfying the interface expected by ReleaseModeModelRunner for its TGen parameter.
int LookupArgIndex(const std::string &)
int LookupResultIndex(const std::string &)
ReleaseModeModelRunner(LLVMContext &Ctx, const FType &InputSpec, StringRef DecisionName, const EmbeddedModelRunnerOptions &Options={})
FeatureNames' type should be an indexed collection of std::string, like std::array or std::vector,...
static bool classof(const MLModelRunner *R)
virtual ~ReleaseModeModelRunner()=default
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
LLVM Value Representation.
Definition: Value.h:74
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Low
Lower the current thread's priority such that it does not affect foreground tasks significantly.
bool isEmbeddedModelEvaluatorValid()
bool isEmbeddedModelEvaluatorValid< NoopSavedModelImpl >()
const char *const DecisionName
ReleaseModeModelRunner - production mode implementation of the MLModelRunner.
EmbeddedModelRunnerOptions & setFeedPrefix(StringRef Value)
StringRef FeedPrefix
Feed and Fetch feature prefixes - i.e.
EmbeddedModelRunnerOptions & setModelSelector(StringRef Value)
StringRef ModelSelector
ModelSelector is the name (recognized by the AOT-ed model) of a sub-model to use.
EmbeddedModelRunnerOptions & setFetchPrefix(StringRef Value)