@@ -74,11 +74,11 @@ namespace {
74
74
// / An InlineEvent, used by TrainingLogger.
75
75
struct InlineEvent {
76
76
// / What the default policy's decision would have been.
77
- bool DefaultDecision = false ;
77
+ int64_t DefaultDecision = 0 ;
78
78
79
79
// / What we advised. When training off the default policy, this is the same as
80
80
// / DefaultDecision.
81
- bool AdvisedDecision = false ;
81
+ int64_t AdvisedDecision = 0 ;
82
82
83
83
// / What actually happened. This would be 'false' in the case of an inline
84
84
// / error, even if AdvisedDecision were true, otherwise it agrees with
@@ -109,91 +109,16 @@ class TrainingLogger final {
109
109
void print ();
110
110
111
111
private:
112
- // / Write the values of one tensor as a list.
113
- template <typename T>
114
- void writeTensorValues (raw_fd_ostream &OutFile, const char *TensorData,
115
- size_t ElemCount) const {
116
- OutFile << " [" ;
117
- const T *TypedData = reinterpret_cast <const T *>(TensorData);
118
- for (size_t I = 0 ; I < ElemCount; ++I) {
119
- if (I > 0 )
120
- OutFile << " , " ;
121
- OutFile << TypedData[I];
122
- }
123
- OutFile << " ]" ;
124
- }
125
-
126
- // / Write a list of tensors as a sequence of TensorFlow FeatureList protobufs.
127
- // / The tensors are assumed to be stored contiguously, in row-major format,
128
- // / in the TensorData buffer. Each tensor has the shape given by Spec. The
129
- // / feature name in the output is either the provided LoggingName, if
130
- // / specified, otherwise it's the name of the tensor (as given by Spec).
131
- template <typename T>
132
- void
133
- writeTensorsAsFeatureLists (raw_fd_ostream &OutFile, const TensorSpec &Spec,
134
- const T *TensorData, size_t TensorCount,
135
- Optional<StringRef> LoggingName = None) const {
136
- writeRawTensorsAsFeatureLists (OutFile, Spec,
137
- reinterpret_cast <const char *>(TensorData),
138
- TensorCount, LoggingName);
139
- }
140
-
141
- // / Untyped implementation of the API above.
142
- void
143
- writeRawTensorsAsFeatureLists (raw_fd_ostream &OutFile, const TensorSpec &Spec,
144
- const char *TensorData, size_t TensorCount,
145
- Optional<StringRef> LoggingName = None) const {
146
- const char *FieldName = " <invalid>" ;
147
- std::function<void (const char *)> ValueWriter;
148
- // The 'Feature' protobuf only has 3 possible fields: float_list,
149
- // int64_list, or bytes_list, so we capture int32 values as int64. We don't
150
- // support any other types.
151
- if (Spec.isElementType <int64_t >()) {
152
- FieldName = " int64_list" ;
153
- ValueWriter = [&](const char *Data) {
154
- writeTensorValues<int64_t >(OutFile, Data, Spec.getElementCount ());
155
- };
156
- } else if (Spec.isElementType <int32_t >()) {
157
- FieldName = " int64_list" ;
158
- ValueWriter = [&](const char *Data) {
159
- writeTensorValues<int32_t >(OutFile, Data, Spec.getElementCount ());
160
- };
161
-
162
- } else if (Spec.isElementType <float >()) {
163
- FieldName = " float_list" ;
164
- ValueWriter = [&](const char *Data) {
165
- writeTensorValues<float >(OutFile, Data, Spec.getElementCount ());
166
- };
167
-
168
- } else
169
- llvm_unreachable (" Unsupported tensor type." );
170
-
171
- OutFile << " feature_list: {\n " ;
172
- OutFile << " key: "
173
- << " \" " << (LoggingName ? *LoggingName : Spec.name ()) << " \" " ;
174
- OutFile << " value: {\n " ;
175
- size_t TensorByteSize = Spec.getElementCount () * Spec.getElementByteSize ();
176
- for (const char *P = TensorData,
177
- *E = TensorData + TensorByteSize * TensorCount;
178
- P < E; P += TensorByteSize) {
179
- OutFile << " feature: { " << FieldName << " : { value: " ;
180
- ValueWriter (P);
181
- OutFile << " } }\n " ;
182
- }
183
- OutFile << " }\n " ;
184
- OutFile << " }\n " ;
185
- }
186
-
187
112
StringRef LogFileName;
188
113
const ModelUnderTrainingRunner *const MUTR;
189
- std::vector<InlineFeatures> Features;
190
- std::vector<int64_t > DefaultDecisions;
191
- // We store all outputs as data blobs, but we always expect to have one, the
192
- // first one, representing the decision. While we could track that separately,
193
- // for uniformity, we store it, generically, here.
194
- std::vector<std::vector<char >> Outputs;
114
+ std::unique_ptr<Logger> L;
195
115
std::vector<bool > Effects;
196
- std::vector<int64_t > Rewards;
116
+ // / There's at least one output. We'll set this to a different value if MUTR
117
+ // / is avaliable.
118
+ size_t OutputCount = 1 ;
119
+ // / Set these 2 clearly OOB, to make sure we set them later.
120
+ size_t DefaultDecisionPos = std::numeric_limits<size_t >::max();
121
+ size_t DecisionPos = std::numeric_limits<size_t >::max();
197
122
};
198
123
199
124
// / An extension of the MLInlineAdvisor for the 'development' mode, targeting
@@ -331,8 +256,8 @@ class LoggingMLInlineAdvice : public MLInlineAdvice {
331
256
TrainingLogger &Logger;
332
257
const Optional<size_t > CallerSizeEstimateBefore;
333
258
const Optional<size_t > CalleeSizeEstimateBefore;
334
- const bool DefaultDecision;
335
- const bool Mandatory;
259
+ const int64_t DefaultDecision;
260
+ const int64_t Mandatory;
336
261
};
337
262
338
263
// / A pseudo model runner. We use it to store feature values when collecting
@@ -402,69 +327,62 @@ class ModelUnderTrainingRunner final : public MLModelRunner {
402
327
TrainingLogger::TrainingLogger (StringRef LogFileName,
403
328
const ModelUnderTrainingRunner *MUTR)
404
329
: LogFileName(LogFileName), MUTR(MUTR) {
330
+ // The first output is the inlining decision.
331
+ if (MUTR)
332
+ OutputCount = MUTR->outputSpecs ().size ();
333
+ std::vector<Logger::LoggedFeatureSpec> FT;
334
+
405
335
for (size_t I = 0 ; I < NumberOfFeatures; ++I)
406
- Features.push_back (InlineFeatures ());
336
+ FT.push_back (
337
+ {TensorSpec::createSpec<int64_t >(FeatureNameMap.at (I), {1 }), None});
338
+ for (size_t I = 1 ; I < OutputCount; ++I)
339
+ FT.push_back ({MUTR->outputSpecs ()[I], MUTR->outputNames ()[I]});
407
340
408
- // The first output is the inlining decision.
409
- auto OutputCount = MUTR ? MUTR->outputSpecs ().size () : 1 ;
410
- Outputs.assign (OutputCount, std::vector<char >());
341
+ DefaultDecisionPos = FT.size ();
342
+ FT.push_back (
343
+ {TensorSpec::createSpec<int64_t >(DefaultDecisionName, {1 }), None});
344
+
345
+ DecisionPos = FT.size ();
346
+ FT.push_back ({TensorSpec::createSpec<int64_t >(DecisionName, {1 }), None});
347
+
348
+ L = std::make_unique<Logger>(
349
+ FT, TensorSpec::createSpec<int64_t >(RewardName, {1 }),
350
+ InlineSizeEstimatorAnalysis::isEvaluatorRequested ());
411
351
}
412
352
413
353
// / Log one inlining event.
414
354
void TrainingLogger::logInlineEvent (const InlineEvent &Event,
415
355
const MLModelRunner &ModelRunner) {
416
- for (size_t I = 0 ; I < NumberOfFeatures; ++I)
417
- Features[I].push_back (ModelRunner.getFeature (I));
356
+ size_t CurrentFeature = 0 ;
357
+ for (; CurrentFeature < NumberOfFeatures; ++CurrentFeature) {
358
+ int64_t F = ModelRunner.getFeature (CurrentFeature);
359
+ L->logTensorValue (CurrentFeature, &F);
360
+ }
418
361
419
- Effects.push_back (Event.Effect );
420
- Rewards.push_back (Event.Reward );
421
- DefaultDecisions.push_back (Event.DefaultDecision );
422
- int64_t Advice = static_cast <int64_t >(Event.AdvisedDecision );
423
- const char *AdviceData = reinterpret_cast <const char *>(&Advice);
424
- Outputs[0 ].insert (Outputs[0 ].end (), AdviceData, AdviceData + sizeof (int64_t ));
425
- for (size_t I = 1 ; I < Outputs.size (); ++I) {
362
+ for (size_t I = 1 ; I < OutputCount; ++I) {
426
363
const auto &Result = *MUTR->lastEvaluationResult ();
427
364
auto &Spec = MUTR->outputSpecs ()[I];
428
365
const char *RawData =
429
366
reinterpret_cast <const char *>(Result.getUntypedTensorValue (I));
430
- Outputs[I]. insert (Outputs[I]. end () , RawData,
431
- RawData +
432
- Spec. getElementCount () * Spec. getElementByteSize ()) ;
367
+ L-> logTensorValue (CurrentFeature , RawData,
368
+ Spec. getElementCount () * Spec. getElementByteSize ());
369
+ ++CurrentFeature ;
433
370
}
371
+
372
+ assert (CurrentFeature == DefaultDecisionPos);
373
+ L->logTensorValue (DefaultDecisionPos, &Event.DefaultDecision );
374
+ L->logTensorValue (DecisionPos, &Event.AdvisedDecision );
375
+ if (InlineSizeEstimatorAnalysis::isEvaluatorRequested ())
376
+ L->logReward (Event.Reward );
377
+
378
+ // For debugging / later use
379
+ Effects.push_back (Event.Effect );
434
380
}
435
381
436
382
void TrainingLogger::print () {
437
383
std::error_code EC;
438
384
raw_fd_ostream OutFile (LogFileName, EC);
439
- size_t NumberOfRecords = Rewards.size ();
440
- if (NumberOfRecords == 0 )
441
- return ;
442
-
443
- OutFile << " feature_lists: {\n " ;
444
- for (size_t I = 0 ; I < Features.size (); ++I)
445
- writeTensorsAsFeatureLists (
446
- OutFile, TensorSpec::createSpec<int64_t >(FeatureNameMap.at (I), {1 }),
447
- Features[I].data (), NumberOfRecords);
448
-
449
- writeTensorsAsFeatureLists (
450
- OutFile, TensorSpec::createSpec<int64_t >(DefaultDecisionName, {1 }),
451
- DefaultDecisions.data (), NumberOfRecords);
452
-
453
- writeRawTensorsAsFeatureLists (
454
- OutFile, TensorSpec::createSpec<int64_t >(DecisionName, {1 }),
455
- Outputs[0 ].data (), NumberOfRecords);
456
-
457
- if (InlineSizeEstimatorAnalysis::isEvaluatorRequested ())
458
- writeTensorsAsFeatureLists (OutFile,
459
- TensorSpec::createSpec<int64_t >(RewardName, {1 }),
460
- Rewards.data (), NumberOfRecords);
461
-
462
- for (size_t I = 1 ; I < Outputs.size (); ++I)
463
- writeRawTensorsAsFeatureLists (OutFile, MUTR->outputSpecs ()[I],
464
- Outputs[I].data (), NumberOfRecords,
465
- StringRef (MUTR->outputNames ()[I]));
466
-
467
- OutFile << " }\n " ;
385
+ L->print (OutFile);
468
386
}
469
387
470
388
DevelopmentModeMLInlineAdvisor::DevelopmentModeMLInlineAdvisor (
0 commit comments