| 18 | } |
| 19 | |
| 20 | TypedValueRef<FormattedTensorValue> FormatTransformation::to( |
| 21 | const FormattedTensorValue& tensor, const FT& target, |
| 22 | const std::string& scope) const { |
| 23 | std::vector<int32_t> pattern; |
| 24 | Format format = tensor.format(); |
| 25 | if (format == target) |
| 26 | return as(tensor, target); |
| 27 | |
| 28 | auto&& shape = tensor.value().shape().cast<ShapeValue>(); |
| 29 | if (format == FT::NHWC && (target == FT::NCHW || target == FT::DEFAULT)) { |
| 30 | // FIXME(czh): temporary fast path for group conv 5D weight. |
| 31 | if (shape.ndim == 5) { |
| 32 | pattern = {0, 1, 4, 2, 3}; |
| 33 | } else if (shape.ndim == 4) { |
| 34 | pattern = {0, 3, 1, 2}; |
| 35 | } else { |
| 36 | mgb_throw( |
| 37 | MegBrainError, |
| 38 | "Unsupport format conversion for tensor %s(shape=%s) from %s to %s", |
| 39 | tensor.to_string().c_str(), shape.to_string().c_str(), |
| 40 | format.to_string().c_str(), Format(target).to_string().c_str()); |
| 41 | } |
| 42 | } else if ((format == FT::NCHW || format == FT::DEFAULT) && target == FT::NHWC) { |
| 43 | if (shape.ndim == 5) { |
| 44 | pattern = {0, 1, 3, 4, 2}; |
| 45 | } else if (shape.ndim == 4) { |
| 46 | pattern = {0, 2, 3, 1}; |
| 47 | } else { |
| 48 | mgb_throw( |
| 49 | MegBrainError, |
| 50 | "Unsupport format conversion for tensor %s(shape=%s) from %s to %s", |
| 51 | tensor.to_string().c_str(), shape.to_string().c_str(), |
| 52 | format.to_string().c_str(), Format(target).to_string().c_str()); |
| 53 | } |
| 54 | } else { |
| 55 | mgb_throw( |
| 56 | MegBrainError, |
| 57 | "Unsupport format conversion for tensor %s(shape=%s) from %s to %s", |
| 58 | tensor.to_string().c_str(), shape.to_string().c_str(), |
| 59 | format.to_string().c_str(), Format(target).to_string().c_str()); |
| 60 | } |
| 61 | mgb_log_debug( |
| 62 | "Change tensor %s from %s to %s", tensor.to_string().c_str(), |
| 63 | format.to_string().c_str(), Format(target).to_string().c_str()); |
| 64 | auto output = |
| 65 | imperative::apply(*Dimshuffle::make(pattern, scope), {tensor.value()})[0]; |
| 66 | return m_value_type.make(output, target); |
| 67 | } |
| 68 | |
| 69 | inline ValueRef FormatTransformation::unwrap_input(const ValueRef& input) const { |
| 70 | if (auto format_input = input.as_ref(m_value_type)) { |
no test coverage detected