| 58 | } |
| 59 | |
| 60 | Ref<Op> Graph::addConv(const std::string& name, |
| 61 | const Ref<Op>& srcOp, |
| 62 | Activation activation, |
| 63 | Fusion fusion) |
| 64 | { |
| 65 | if (fusion != Fusion::None && !engine->isConvSupported(fusion)) |
| 66 | { |
| 67 | // If the engine does not support the specified fused convolution, split it into two ops |
| 68 | switch (fusion) |
| 69 | { |
| 70 | case Fusion::UpsampleSrc0: |
| 71 | { |
| 72 | auto srcUpsample = addUpsample(name + "_upsample", srcOp); |
| 73 | return addConv(name, srcUpsample, activation); |
| 74 | } |
| 75 | |
| 76 | case Fusion::PoolDst: |
| 77 | { |
| 78 | auto conv = addConv(name, srcOp, activation); |
| 79 | return addPool(name + "_pool", conv); |
| 80 | } |
| 81 | |
| 82 | default: |
| 83 | throw std::invalid_argument("unsupported convolution fusion"); |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | const std::string weightName = name + ".weight"; |
| 88 | const std::string biasName = name + ".bias"; |
| 89 | Ref<Tensor> weight = (*constTensors)[weightName]; |
| 90 | Ref<Tensor> bias = (*constTensors)[biasName]; |
| 91 | |
| 92 | if (weight->getRank() != 4 || bias->getRank() != 1) |
| 93 | throw std::invalid_argument("invalid convolution weight/bias"); |
| 94 | |
| 95 | Device* device = engine->getDevice(); |
| 96 | const int blockC = device->getTensorBlockC(); |
| 97 | |
| 98 | TensorDims finalWeightDims{round_up(weight->getO(), blockC), |
| 99 | round_up(weight->getI(), blockC), |
| 100 | weight->getH(), |
| 101 | weight->getW()}; |
| 102 | |
| 103 | TensorDesc finalWeightDesc = {weight->getDims(), |
| 104 | finalWeightDims, |
| 105 | device->getWeightLayout(), |
| 106 | device->getWeightDataType()}; |
| 107 | |
| 108 | TensorDesc finalBiasDesc = {bias->getDims(), |
| 109 | {round_up(bias->getX(), blockC)}, |
| 110 | TensorLayout::x, |
| 111 | device->getTensorDataType()}; |
| 112 | |
| 113 | auto srcAlloc = tensorAllocs[srcOp.get()]; |
| 114 | auto conv = engine->newConv({srcAlloc->desc, finalWeightDesc, finalBiasDesc, activation, fusion, fastMath}); |
| 115 | conv->setName(name); |
| 116 | auto dstAlloc = addOp(conv, {srcOp}, conv->getDstDesc()); |
| 117 |
no test coverage detected