1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15
16 #include "tensorflow/stream_executor/dnn.h"
17
18 #include "absl/hash/hash.h"
19 #include "absl/strings/str_cat.h"
20 #include "absl/strings/str_format.h"
21
22 namespace stream_executor {
23 namespace dnn {
24
25 constexpr DataType ToDataType<float>::value;
26 constexpr DataType ToDataType<double>::value;
27 constexpr DataType ToDataType<Eigen::half>::value;
28 constexpr DataType ToDataType<int8>::value;
29 constexpr DataType ToDataType<int32>::value;
30
hash() const31 uint64 AlgorithmDesc::hash() const {
32 auto p = std::make_pair(algo_id(), tensor_ops_enabled());
33 return absl::Hash<decltype(p)>()(p);
34 }
35
ToString() const36 std::string AlgorithmDesc::ToString() const {
37 if (tensor_ops_enabled()) {
38 return absl::StrCat(algo_id(), "#TC");
39 } else {
40 return absl::StrCat(algo_id());
41 }
42 }
43
GetConvolveAlgorithms(bool with_winograd_nonfused,int cc_major,int cc_minor,std::vector<AlgorithmDesc> * out_algorithms)44 bool DnnSupport::GetConvolveAlgorithms(
45 bool with_winograd_nonfused, int cc_major, int cc_minor,
46 std::vector<AlgorithmDesc>* out_algorithms) {
47 return false;
48 }
49
GetMIOpenConvolveAlgorithms(dnn::ConvolutionKind,dnn::DataType,Stream *,const dnn::BatchDescriptor &,DeviceMemoryBase input_data,const dnn::FilterDescriptor &,DeviceMemoryBase filter_data,const dnn::BatchDescriptor &,DeviceMemoryBase output_data,const dnn::ConvolutionDescriptor &,ScratchAllocator * scratch_allocator,std::vector<ProfileResult> *)50 bool DnnSupport::GetMIOpenConvolveAlgorithms(
51 dnn::ConvolutionKind /*kind*/, dnn::DataType /*element_type*/,
52 Stream* /*stream*/, const dnn::BatchDescriptor& /*input_descriptor*/,
53 DeviceMemoryBase input_data,
54 const dnn::FilterDescriptor& /*filter_descriptor*/,
55 DeviceMemoryBase filter_data,
56 const dnn::BatchDescriptor& /*output_descriptor*/,
57 DeviceMemoryBase output_data,
58 const dnn::ConvolutionDescriptor& /*convolution_descriptor*/,
59 ScratchAllocator* scratch_allocator,
60 std::vector<ProfileResult>* /*out_algorithms*/) {
61 return false;
62 }
63
GetRnnAlgorithms(std::vector<AlgorithmDesc> * out_algorithms)64 bool DnnSupport::GetRnnAlgorithms(std::vector<AlgorithmDesc>* out_algorithms) {
65 return false;
66 }
67
GetConvolveBackwardDataAlgorithms(bool with_winograd_nonfused,int cc_major,int cc_minor,std::vector<AlgorithmDesc> * out_algorithms)68 bool DnnSupport::GetConvolveBackwardDataAlgorithms(
69 bool with_winograd_nonfused, int cc_major, int cc_minor,
70 std::vector<AlgorithmDesc>* out_algorithms) {
71 return false;
72 }
73
GetConvolveBackwardFilterAlgorithms(bool with_winograd_nonfused,int cc_major,int cc_minor,std::vector<AlgorithmDesc> * out_algorithms)74 bool DnnSupport::GetConvolveBackwardFilterAlgorithms(
75 bool with_winograd_nonfused, int cc_major, int cc_minor,
76 std::vector<AlgorithmDesc>* out_algorithms) {
77 return false;
78 }
79
QuantizedActivationModeString(QuantizedActivationMode mode)80 std::string QuantizedActivationModeString(QuantizedActivationMode mode) {
81 switch (mode) {
82 case dnn::QuantizedActivationMode::k8Bit:
83 return "uint8";
84 case dnn::QuantizedActivationMode::k16Bit:
85 return "uint16";
86 case dnn::QuantizedActivationMode::k32Bit:
87 return "int32";
88 default:
89 LOG(FATAL) << "Unknown quantized_activation_mode "
90 << static_cast<int32>(mode);
91 }
92 return "unknown quantized_activation_mode";
93 }
94
ActivationModeString(ActivationMode mode)95 std::string ActivationModeString(ActivationMode mode) {
96 switch (mode) {
97 case ActivationMode::kNone:
98 return "none";
99 case ActivationMode::kSigmoid:
100 return "sigmoid";
101 case ActivationMode::kRelu:
102 return "relu";
103 case ActivationMode::kRelu6:
104 return "relu6";
105 case ActivationMode::kReluX:
106 return "reluX";
107 case ActivationMode::kTanh:
108 return "tanh";
109 case ActivationMode::kBandPass:
110 return "bandpass";
111 default:
112 LOG(FATAL) << "Unknown activation_mode " << static_cast<int32>(mode);
113 }
114 return "unknown activation_mode";
115 }
116
ElementwiseOperationString(ElementwiseOperation op)117 std::string ElementwiseOperationString(ElementwiseOperation op) {
118 switch (op) {
119 case ElementwiseOperation::kAdd:
120 return "add";
121 case ElementwiseOperation::kMultiply:
122 return "multiply";
123 default:
124 LOG(FATAL) << "Unknown elementwise op " << static_cast<int32>(op);
125 }
126 return "unknown element wise op";
127 }
128
DataLayoutString(DataLayout layout)129 std::string DataLayoutString(DataLayout layout) {
130 switch (layout) {
131 case DataLayout::kYXDepthBatch:
132 return "YXDepthBatch";
133 case DataLayout::kYXBatchDepth:
134 return "YXBatchDepth";
135 case DataLayout::kBatchYXDepth:
136 return "BatchYXDepth";
137 case DataLayout::kBatchDepthYX:
138 return "BatchDepthYX";
139 case DataLayout::kBatchDepthYX4:
140 return "BatchDepthYX4";
141 default:
142 LOG(FATAL) << "Unknown data layout " << static_cast<int32>(layout);
143 }
144 return "unknown data layout";
145 }
146
FilterLayoutString(FilterLayout layout)147 std::string FilterLayoutString(FilterLayout layout) {
148 switch (layout) {
149 case FilterLayout::kOutputInputYX:
150 return "OutputInputYX";
151 case FilterLayout::kOutputYXInput:
152 return "OutputYXInput";
153 case FilterLayout::kOutputInputYX4:
154 return "OutputInputYX4";
155 case FilterLayout::kInputYXOutput:
156 return "InputYXOutput";
157 case FilterLayout::kYXInputOutput:
158 return "YXInputOutput";
159 default:
160 LOG(FATAL) << "Unknown filter layout " << static_cast<int32>(layout);
161 }
162 return "unknown filter layout";
163 }
164
PadAlignmentString(PadAlignment alignment)165 std::string PadAlignmentString(PadAlignment alignment) {
166 switch (alignment) {
167 case PadAlignment::kDefault:
168 return "default";
169 case PadAlignment::kCudnnPadding:
170 return "cuDNN padding";
171 case PadAlignment::kTensorFlowPadding:
172 return "TensorFlow padding";
173 }
174 return "unknown pad alignment";
175 }
176
operator <<(std::ostream & str,dnn::PadAlignment alignment)177 std::ostream& operator<<(std::ostream& str, dnn::PadAlignment alignment) {
178 return str << PadAlignmentString(alignment);
179 }
180
ShortPoolingModeString(PoolingMode mode)181 std::string ShortPoolingModeString(PoolingMode mode) {
182 switch (mode) {
183 case PoolingMode::kMaximum:
184 return "Max";
185 case PoolingMode::kAverage:
186 return "Avg";
187 default:
188 LOG(FATAL) << "Unknown filter layout " << static_cast<int32>(mode);
189 }
190 return "unknown filter layout";
191 }
192
GetDimIndices(const DataLayout & layout,const int data_dims)193 std::tuple<int, int, int> GetDimIndices(const DataLayout& layout,
194 const int data_dims) {
195 int depth_idx, batch_idx, spatial_idx;
196 switch (layout) {
197 case DataLayout::kYXBatchDepth:
198 depth_idx = data_dims - 1;
199 batch_idx = data_dims - 2;
200 spatial_idx = 0;
201 break;
202
203 case DataLayout::kYXDepthBatch:
204 depth_idx = data_dims - 2;
205 batch_idx = data_dims - 1;
206 spatial_idx = 0;
207 break;
208
209 case DataLayout::kBatchYXDepth:
210 depth_idx = data_dims - 1;
211 batch_idx = 0;
212 spatial_idx = 1;
213 break;
214
215 case DataLayout::kBatchDepthYX:
216 case DataLayout::kBatchDepthYX4:
217 depth_idx = 1;
218 batch_idx = 0;
219 spatial_idx = 2;
220 break;
221
222 default:
223 LOG(FATAL) << "Unknown layout " << layout;
224 }
225
226 return std::make_tuple(depth_idx, batch_idx, spatial_idx);
227 }
228
ReorderDims(const std::vector<int64> & input,const DataLayout & from,const DataLayout & to)229 std::vector<int64> ReorderDims(const std::vector<int64>& input,
230 const DataLayout& from, const DataLayout& to) {
231 if (from == to) return input;
232
233 int d_idx_from, b_idx_from, spatial_idx_from;
234 int d_idx_to, b_idx_to, spatial_idx_to;
235
236 std::tie(d_idx_from, b_idx_from, spatial_idx_from) =
237 GetDimIndices(from, input.size());
238 std::tie(d_idx_to, b_idx_to, spatial_idx_to) =
239 GetDimIndices(to, input.size());
240
241 std::vector<int64> reordered(input.size());
242 reordered[b_idx_to] = input[b_idx_from];
243 reordered[d_idx_to] = input[d_idx_from];
244
245 for (size_t i = 0; i < input.size() - 2;
246 i++, spatial_idx_from++, spatial_idx_to++) {
247 reordered[spatial_idx_to] = input[spatial_idx_from];
248 }
249
250 return reordered;
251 }
252
253 // -- AlgorithmConfig
254
ToString() const255 std::string AlgorithmConfig::ToString() const {
256 std::string algo = "none";
257 if (algorithm().has_value()) {
258 algo = algorithm()->ToString();
259 }
260 std::string algo_no_scratch = "none";
261 if (algorithm_no_scratch().has_value()) {
262 algo_no_scratch = algorithm_no_scratch()->ToString();
263 }
264 return absl::StrCat(algo, ", ", algo_no_scratch);
265 }
266
267 // -- BatchDescriptor
268
BatchDescriptor(int ndims)269 BatchDescriptor::BatchDescriptor(int ndims)
270 : value_max_(0.0),
271 value_min_(0.0),
272 quantized_activation_mode_(QuantizedActivationMode::k8Bit) {
273 tensor_.mutable_dimensions()->Resize(ndims + 2, 0);
274 set_layout(DataLayout::kYXDepthBatch);
275 }
276
BatchDescriptor()277 BatchDescriptor::BatchDescriptor() : BatchDescriptor(/*ndims=*/2) {}
278
full_dims(const DataLayout & layout) const279 std::vector<int64> BatchDescriptor::full_dims(const DataLayout& layout) const {
280 std::vector<int64> bdyx_dims(ndims() + 2);
281 bdyx_dims[0] = count();
282 bdyx_dims[1] = feature_map_count();
283 std::copy(spatial_size().begin(), spatial_size().end(),
284 bdyx_dims.begin() + 2);
285 return ReorderDims(bdyx_dims, DataLayout::kBatchDepthYX, layout);
286 }
287
full_strides(const DataLayout & layout) const288 std::vector<int64> BatchDescriptor::full_strides(
289 const DataLayout& layout) const {
290 if (this->layout() == DataLayout::kBatchDepthYX4) {
291 LOG(FATAL)
292 << "Cannot compute full strides for batch descriptor " << ToString()
293 << ", because its layout is kBatchDepthYX4. In fact, "
294 "cudnnSetTensorNdDescriptor doesn't work for kBatchDepthYX4 at all. "
295 "Use cudnnSetTensor4DDescriptor to set cudnnTensorDescriptor_t "
296 "instead.";
297 }
298 std::vector<int64> phys_dims = full_dims(this->layout());
299 std::vector<int64> phys_strides(phys_dims.size());
300 phys_strides[ndims() + 1] = 1;
301 for (int i = ndims(); i >= 0; i--) {
302 phys_strides[i] = phys_strides[i + 1] * phys_dims[i + 1];
303 }
304 return ReorderDims(phys_strides, this->layout(), layout);
305 }
306
CloneFrom(const BatchDescriptor & other)307 void BatchDescriptor::CloneFrom(const BatchDescriptor& other) {
308 tensor_ = other.tensor_;
309 value_max_ = other.value_max_;
310 value_min_ = other.value_min_;
311 quantized_activation_mode_ = other.quantized_activation_mode_;
312 }
313
ToString() const314 std::string BatchDescriptor::ToString() const {
315 std::string spatial;
316 for (int i = 0; i < ndims(); i++) {
317 absl::StrAppendFormat(&spatial, "%d ", spatial_size()[i]);
318 }
319 return absl::StrFormat(
320 "{count: %d feature_map_count: %d spatial: %s "
321 "value_min: %f value_max: %f layout: %s}",
322 count(), feature_map_count(), spatial, value_min_, value_max_,
323 DataLayoutString(layout()));
324 }
325
ToShortString() const326 std::string BatchDescriptor::ToShortString() const {
327 // All the constituent strings are less than 15 characters, so the
328 // small string optimization ensures that there will be at most one
329 // heap memory allocation.
330 std::string depth = absl::StrCat("d", feature_map_count());
331 std::string batch = absl::StrCat("b", count());
332
333 std::string spatial = "s";
334 for (int i = 0; i < ndims(); i++) {
335 absl::StrAppendFormat(&spatial, "%d ", spatial_size()[i]);
336 }
337
338 std::string suffix;
339 if (value_min() != value_max()) {
340 absl::StrAppend(&suffix, "[", value_min(), ";", value_max(), "]");
341 }
342 if (quantized_activation_mode() == QuantizedActivationMode::k16Bit) {
343 suffix += "_16bit";
344 }
345
346 switch (layout()) {
347 case DataLayout::kYXDepthBatch:
348 return absl::StrCat(spatial, depth, batch, suffix);
349 case DataLayout::kYXBatchDepth:
350 return absl::StrCat(spatial, batch, depth, suffix);
351 case DataLayout::kBatchYXDepth:
352 return absl::StrCat(batch, spatial, depth, suffix);
353 case DataLayout::kBatchDepthYX:
354 return absl::StrCat(batch, depth, spatial, suffix);
355 case DataLayout::kBatchDepthYX4:
356 return absl::StrCat(batch, depth, spatial, suffix, "(VECT_C)");
357 default:
358 LOG(FATAL) << "Unknown layout " << static_cast<int32>(layout());
359 return ""; // Avoid return warning (unreachable)
360 }
361 }
362
NodesPerFeatureMap() const363 int64 BatchDescriptor::NodesPerFeatureMap() const {
364 int64 ret = 1;
365 for (int i = 0; i < ndims(); i++) {
366 ret *= spatial_size()[i];
367 }
368 return ret;
369 }
370
NodesAcrossFeatureMaps() const371 int64 BatchDescriptor::NodesAcrossFeatureMaps() const {
372 return NodesPerFeatureMap() * feature_map_count();
373 }
374
ElementCount() const375 int64 BatchDescriptor::ElementCount() const {
376 return count() * feature_map_count() * NodesPerFeatureMap();
377 }
378
FullyConnectedWeightCount(const BatchDescriptor & input,const BatchDescriptor & output)379 int64 BatchDescriptor::FullyConnectedWeightCount(
380 const BatchDescriptor& input, const BatchDescriptor& output) {
381 return input.NodesAcrossFeatureMaps() * output.NodesAcrossFeatureMaps();
382 }
383
FullyConnectedBiasCount(const BatchDescriptor & output)384 int64 BatchDescriptor::FullyConnectedBiasCount(const BatchDescriptor& output) {
385 return output.NodesAcrossFeatureMaps();
386 }
387
DepthConcatenateOutputDescriptor(port::ArraySlice<dnn::BatchDescriptor> inputs)388 BatchDescriptor BatchDescriptor::DepthConcatenateOutputDescriptor(
389 port::ArraySlice<dnn::BatchDescriptor> inputs) {
390 if (inputs.empty()) {
391 return BatchDescriptor();
392 }
393 int feature_map_count = 0;
394 for (const auto& dimensions : inputs) {
395 feature_map_count += dimensions.feature_map_count();
396 }
397 BatchDescriptor output = inputs[0];
398 output.set_feature_map_count(feature_map_count);
399 return output;
400 }
401
ToProto(DataType data_type) const402 TensorDescriptorProto BatchDescriptor::ToProto(DataType data_type) const {
403 CHECK_EQ(0.0, value_max_);
404 CHECK_EQ(0.0, value_min_);
405 CHECK(quantized_activation_mode_ == QuantizedActivationMode::k8Bit);
406
407 TensorDescriptorProto ret = tensor_;
408 ret.set_data_type(data_type);
409 return ret;
410 }
411
412 // -- FilterDescriptor
413
FilterDescriptor(int ndims)414 FilterDescriptor::FilterDescriptor(int ndims) {
415 tensor_.mutable_dimensions()->Resize(ndims + 2, 0);
416 set_layout(FilterLayout::kOutputInputYX);
417 }
418
FilterDescriptor()419 FilterDescriptor::FilterDescriptor() : FilterDescriptor(/*ndims=*/2) {}
420
~FilterDescriptor()421 FilterDescriptor::~FilterDescriptor() {}
422
CloneFrom(const FilterDescriptor & other)423 void FilterDescriptor::CloneFrom(const FilterDescriptor& other) {
424 tensor_ = other.tensor_;
425 }
426
ToString() const427 std::string FilterDescriptor::ToString() const {
428 std::string desc = absl::StrFormat(
429 "{output_feature_map_count: %d input_feature_map_count: %d "
430 "layout: %s shape: ",
431 output_feature_map_count(), input_feature_map_count(),
432 FilterLayoutString(layout()));
433 for (int i = 0; i < ndims(); i++) {
434 absl::StrAppendFormat(&desc, "%d ", input_filter_dims()[i]);
435 }
436 absl::StrAppend(&desc, "}");
437
438 return desc;
439 }
440
ToShortString() const441 std::string FilterDescriptor::ToShortString() const {
442 // All the constituent strings are less than 15 characters, so the
443 // small string optimization ensures that there will be at most one
444 // heap memory allocation.
445 std::string od = absl::StrCat("od", output_feature_map_count());
446 std::string id = absl::StrCat("id", input_feature_map_count());
447
448 std::string spatial = "s";
449 for (int i = 0; i < ndims(); i++) {
450 absl::StrAppendFormat(&spatial, "%d ", input_filter_dims()[i]);
451 }
452
453 switch (layout()) {
454 case FilterLayout::kOutputInputYX:
455 return absl::StrCat(od, id, spatial);
456 case FilterLayout::kOutputYXInput:
457 return absl::StrCat(od, spatial, id);
458 case FilterLayout::kOutputInputYX4:
459 return absl::StrCat(od, id, spatial, "(VECT_C)");
460 case FilterLayout::kInputYXOutput:
461 return absl::StrCat(id, spatial, od);
462 case FilterLayout::kYXInputOutput:
463 return absl::StrCat(spatial, id, od);
464 default:
465 LOG(FATAL) << "Unknown layout " << static_cast<int32>(layout());
466 return ""; // Avoid return warning (unreachable)
467 }
468 }
469
ComputeWeightCount() const470 int64 FilterDescriptor::ComputeWeightCount() const {
471 int64 ret = output_feature_map_count() * input_feature_map_count();
472 for (int i = 0; i < ndims(); i++) {
473 ret *= input_filter_dims()[i];
474 }
475 return ret;
476 }
477
ToProto(DataType data_type) const478 TensorDescriptorProto FilterDescriptor::ToProto(DataType data_type) const {
479 TensorDescriptorProto ret = tensor_;
480 ret.set_data_type(data_type);
481 return ret;
482 }
483
484 // -- ConvolutionDescriptor
485
ConvolutionDescriptor(int ndims)486 ConvolutionDescriptor::ConvolutionDescriptor(int ndims) {
487 proto_.mutable_paddings()->Resize(ndims, 0);
488 proto_.mutable_strides()->Resize(ndims, 1);
489 proto_.mutable_dilations()->Resize(ndims, 1);
490 proto_.set_group_count(1);
491 proto_.set_convolution_mode(ConvolutionMode::CROSS_CORRELATION);
492 }
493
ConvolutionDescriptor()494 ConvolutionDescriptor::ConvolutionDescriptor()
495 : ConvolutionDescriptor(/*ndims=*/2) {}
496
~ConvolutionDescriptor()497 ConvolutionDescriptor::~ConvolutionDescriptor() {}
498
ToString() const499 std::string ConvolutionDescriptor::ToString() const {
500 std::string padding;
501 std::string strides;
502 std::string dilations;
503 for (int i = 0; i < ndims(); i++) {
504 absl::StrAppendFormat(&padding, "%d ", this->padding()[i]);
505 absl::StrAppendFormat(&strides, "%d ", this->strides()[i]);
506 absl::StrAppendFormat(&dilations, "%d ", this->dilations()[i]);
507 }
508
509 return absl::StrFormat(
510 "{zero_padding: %s pad_alignment: %s filter_strides: %s dilation_rates: "
511 "%s}",
512 padding, PadAlignmentString(pad_alignment()), strides, dilations);
513 }
514
ToShortString() const515 std::string ConvolutionDescriptor::ToShortString() const {
516 std::string desc;
517 for (int i = 0; i < ndims(); i++) {
518 if (i > 0) absl::StrAppend(&desc, "_");
519 absl::StrAppendFormat(&desc, "p%d:%d", i, padding()[i]);
520 }
521 for (int i = 0; i < ndims(); i++) {
522 absl::StrAppendFormat(&desc, "_s%d:%d", i, strides()[i]);
523 }
524 for (int i = 0; i < ndims(); i++) {
525 absl::StrAppendFormat(&desc, "_d%d:%d", i, dilations()[i]);
526 }
527 return desc;
528 }
529
530 // -- PoolingDescriptor
531
PoolingDescriptor(int ndims)532 PoolingDescriptor::PoolingDescriptor(int ndims)
533 : mode_(dnn::PoolingMode::kMaximum),
534 ndims_(ndims),
535 propagate_nans_(false),
536 window_(ndims, 0),
537 padding_(ndims, 0),
538 strides_(ndims, 1) {}
539
PoolingDescriptor()540 PoolingDescriptor::PoolingDescriptor() : PoolingDescriptor(/*ndims=*/2) {}
541
CloneFrom(const PoolingDescriptor & other)542 void PoolingDescriptor::CloneFrom(const PoolingDescriptor& other) {
543 mode_ = other.mode_;
544 ndims_ = other.ndims_;
545 window_ = other.window_;
546 padding_ = other.padding_;
547 strides_ = other.strides_;
548 propagate_nans_ = other.propagate_nans_;
549 }
550
ToString() const551 std::string PoolingDescriptor::ToString() const {
552 const char* mode_string =
553 mode_ == dnn::PoolingMode::kMaximum ? "kMaximum" : "kAverage";
554
555 std::string window, strides, padding;
556 for (int i = 0; i < ndims_; i++) {
557 absl::StrAppendFormat(&window, "%d ", window_[i]);
558 absl::StrAppendFormat(&strides, "%d ", strides_[i]);
559 absl::StrAppendFormat(&padding, "%d", padding_[i]);
560 }
561
562 const char* propagate_string = propagate_nans_ ? "Yes" : "No";
563
564 return absl::StrFormat(
565 "{mode: %s window: %s strides: %s padding: %s propagate NaNs: %s}",
566 mode_string, window, strides, padding, propagate_string);
567 }
568
ToShortString() const569 std::string PoolingDescriptor::ToShortString() const {
570 std::string window, strides, padding;
571 for (int i = 0; i < ndims_; i++) {
572 absl::StrAppendFormat(&window, "_w%d:%d", i, window_[i]);
573 absl::StrAppendFormat(&strides, "_s%d:%d", i, strides_[i]);
574 absl::StrAppendFormat(&padding, "_p%d:%d", i, padding_[i]);
575 }
576 return absl::StrCat(mode_ == dnn::PoolingMode::kMaximum ? "max" : "avg",
577 window, strides, padding,
578 propagate_nans_ ? "propagate_nans" : "ignore_nans");
579 }
580
581 // -- NormalizeDescriptor
582
NormalizeDescriptor()583 NormalizeDescriptor::NormalizeDescriptor()
584 : bias_(0.0),
585 range_(0),
586 alpha_(0.0),
587 beta_(0.0),
588 wrap_around_(false),
589 segment_size_(0) {}
590
CloneFrom(const NormalizeDescriptor & other)591 void NormalizeDescriptor::CloneFrom(const NormalizeDescriptor& other) {
592 bias_ = other.bias_;
593 range_ = other.range_;
594 alpha_ = other.alpha_;
595 beta_ = other.beta_;
596 wrap_around_ = other.wrap_around_;
597 segment_size_ = other.segment_size_;
598 }
599
ToString() const600 std::string NormalizeDescriptor::ToString() const {
601 return absl::StrFormat(
602 "{bias: %f range: %d alpha: %f beta: %f wrap_around: %d "
603 "segment_size: %d}",
604 bias_, range_, alpha_, beta_, wrap_around_, segment_size_);
605 }
606
ToShortString() const607 std::string NormalizeDescriptor::ToShortString() const {
608 return absl::StrCat("bias:", bias_, "_range:", range_, "_alpha:", alpha_,
609 "_beta:", beta_, "_wrap:", wrap_around_,
610 "_size:", segment_size_);
611 }
612
IsStatusOk(const port::Status & status,bool report_error)613 bool DnnSupport::IsStatusOk(const port::Status& status, bool report_error) {
614 if (status.ok()) {
615 return true;
616 }
617 if (report_error) {
618 LOG(ERROR) << status.error_message();
619 }
620 return false;
621 }
622
DoCtcLoss(Stream * stream,dnn::DataType element_type,const RnnStateTensorDescriptor & probs_desc,const DeviceMemoryBase probs_data,absl::Span<const int> labels_data,absl::Span<const int> labels_lengths_data,absl::Span<const int> input_lengths_data,DeviceMemoryBase costs_data,const RnnStateTensorDescriptor & grads_desc,DeviceMemoryBase grads_data,DeviceMemory<uint8> scratch_memory,int ctc_loss_algo_id)623 port::Status DnnSupport::DoCtcLoss(
624 Stream* stream, dnn::DataType element_type,
625 const RnnStateTensorDescriptor& probs_desc,
626 const DeviceMemoryBase probs_data, absl::Span<const int> labels_data,
627 absl::Span<const int> labels_lengths_data,
628 absl::Span<const int> input_lengths_data, DeviceMemoryBase costs_data,
629 const RnnStateTensorDescriptor& grads_desc, DeviceMemoryBase grads_data,
630 DeviceMemory<uint8> scratch_memory, int ctc_loss_algo_id) {
631 return port::UnimplementedError("CtcLoss not implemented");
632 }
633
634 } // namespace dnn
635 } // namespace stream_executor
636