Skip to content

Commit 64372d9

Browse files
committed
[NFC][MLInliner] Refactor logging implementation
This prepares it for logging externally-specified outputs. Differential Revision: https://reviews.llvm.org/D85451
1 parent d3dfd8c commit 64372d9

File tree

1 file changed

+93
-27
lines changed

1 file changed

+93
-27
lines changed

llvm/lib/Analysis/DevelopmentModeInlineAdvisor.cpp

Lines changed: 93 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,84 @@ class TrainingLogger final {
8181
void print(raw_fd_ostream &OutFile);
8282

8383
private:
84+
/// Write the values of one tensor as a list.
8485
template <typename T>
85-
void writeTensor(raw_fd_ostream &OutFile, StringRef TensorName,
86-
const std::vector<T> &Tensor);
86+
void writeTensorValues(raw_fd_ostream &OutFile, const char *TensorData,
87+
size_t ElemCount) const {
88+
OutFile << "[";
89+
const T *TypedData = reinterpret_cast<const T *>(TensorData);
90+
for (size_t I = 0; I < ElemCount; ++I) {
91+
if (I > 0)
92+
OutFile << ", ";
93+
OutFile << TypedData[I];
94+
}
95+
OutFile << "]";
96+
}
97+
98+
/// Write a list of tensors as a sequence of TensorFlow FeatureList protobufs.
99+
/// The tensors are assumed to be stored contiguously, in row-major format,
100+
/// in the TensorData buffer. Each tensor has the shape given by Spec. The
101+
/// feature name in the output is either the provided LoggingName, if
102+
/// specified, otherwise it's the name of the tensor (as given by Spec).
103+
template <typename T>
104+
void
105+
writeTensorsAsFeatureLists(raw_fd_ostream &OutFile, const TensorSpec &Spec,
106+
const T *TensorData, size_t TensorCount,
107+
Optional<StringRef> LoggingName = None) const {
108+
writeRawTensorsAsFeatureLists(OutFile, Spec,
109+
reinterpret_cast<const char *>(TensorData),
110+
TensorCount, LoggingName);
111+
}
112+
113+
/// Untyped implementation of the API above.
114+
void
115+
writeRawTensorsAsFeatureLists(raw_fd_ostream &OutFile, const TensorSpec &Spec,
116+
const char *TensorData, size_t TensorCount,
117+
Optional<StringRef> LoggingName = None) const {
118+
const char *FieldName = "<invalid>";
119+
std::function<void(const char *)> ValueWriter;
120+
// The 'Feature' protobuf only has 3 possible fields: float_list,
121+
// int64_list, or bytes_list, so we capture int32 values as int64. We don't
122+
// support any other types.
123+
if (Spec.isElementType<int64_t>()) {
124+
FieldName = "int64_list";
125+
ValueWriter = [&](const char *Data) {
126+
writeTensorValues<int64_t>(OutFile, Data, Spec.getElementCount());
127+
};
128+
} else if (Spec.isElementType<int32_t>()) {
129+
FieldName = "int64_list";
130+
ValueWriter = [&](const char *Data) {
131+
writeTensorValues<int32_t>(OutFile, Data, Spec.getElementCount());
132+
};
133+
134+
} else if (Spec.isElementType<float>()) {
135+
FieldName = "float_list";
136+
ValueWriter = [&](const char *Data) {
137+
writeTensorValues<float>(OutFile, Data, Spec.getElementCount());
138+
};
139+
140+
} else
141+
llvm_unreachable("Unsupported tensor type.");
142+
143+
OutFile << " feature_list: {\n";
144+
OutFile << " key: "
145+
<< "\"" << (LoggingName ? *LoggingName : Spec.name()) << "\" ";
146+
OutFile << "value: {\n";
147+
size_t TensorByteSize = Spec.getElementCount() * Spec.getElementByteSize();
148+
for (const char *P = TensorData,
149+
*E = TensorData + TensorByteSize * TensorCount;
150+
P < E; P += TensorByteSize) {
151+
OutFile << " feature: { " << FieldName << ": { value: ";
152+
ValueWriter(P);
153+
OutFile << " } }\n";
154+
}
155+
OutFile << " }\n";
156+
OutFile << " }\n";
157+
}
87158

88159
std::vector<InlineFeatures> Features;
89-
std::vector<bool> DefaultDecisions;
90-
std::vector<bool> Decisions;
160+
std::vector<int64_t> DefaultDecisions;
161+
std::vector<int64_t> Decisions;
91162
std::vector<bool> Effects;
92163
std::vector<int64_t> Rewards;
93164
};
@@ -294,35 +365,30 @@ void TrainingLogger::logInlineEvent(const InlineEvent &Event,
294365
}
295366

296367
void TrainingLogger::print(raw_fd_ostream &OutFile) {
297-
if (DefaultDecisions.empty())
368+
size_t NumberOfRecords = Decisions.size();
369+
if (NumberOfRecords == 0)
298370
return;
299-
OutFile << "feature_lists: {\n";
300371

301-
for (size_t I = 0; I < Features.size(); I++) {
302-
writeTensor(OutFile, FeatureNameMap.at(I), Features[I]);
303-
}
304-
writeTensor(OutFile, DefaultDecisionName, DefaultDecisions);
305-
writeTensor(OutFile, DecisionName, Decisions);
306-
writeTensor(OutFile, RewardName, Rewards);
372+
OutFile << "feature_lists: {\n";
373+
for (size_t I = 0; I < Features.size(); ++I)
374+
writeTensorsAsFeatureLists(
375+
OutFile, TensorSpec::createSpec<int64_t>(FeatureNameMap.at(I), {1}),
376+
Features[I].data(), NumberOfRecords);
377+
378+
writeTensorsAsFeatureLists(
379+
OutFile, TensorSpec::createSpec<int64_t>(DefaultDecisionName, {1}),
380+
DefaultDecisions.data(), NumberOfRecords);
381+
382+
writeTensorsAsFeatureLists(OutFile,
383+
TensorSpec::createSpec<int64_t>(DecisionName, {1}),
384+
Decisions.data(), NumberOfRecords);
385+
writeTensorsAsFeatureLists(OutFile,
386+
TensorSpec::createSpec<int64_t>(RewardName, {1}),
387+
Rewards.data(), NumberOfRecords);
307388

308389
OutFile << "}\n";
309390
}
310391

311-
template <typename T>
312-
void TrainingLogger::writeTensor(raw_fd_ostream &OutFile, StringRef TensorName,
313-
const std::vector<T> &Tensor) {
314-
OutFile << " feature_list: {\n";
315-
OutFile << " key: "
316-
<< "\"" << TensorName << "\" ";
317-
OutFile << "value: {\n";
318-
for (const auto &Feature : Tensor) {
319-
OutFile << " feature: { int64_list: { value: [" << Feature
320-
<< "] } }\n";
321-
}
322-
OutFile << " }\n";
323-
OutFile << " }\n";
324-
}
325-
326392
DevelopmentModeMLInlineAdvisor::DevelopmentModeMLInlineAdvisor(
327393
Module &M, ModuleAnalysisManager &MAM,
328394
std::unique_ptr<MLModelRunner> ModelRunner,

0 commit comments

Comments
 (0)