| 156 | } |
| 157 | |
| 158 | Ref<Op> Graph::addConcatConv(const std::string& name, |
| 159 | const Ref<Op>& src0Op, |
| 160 | const Ref<Op>& src1Op, |
| 161 | Activation activation, |
| 162 | Fusion fusion) |
| 163 | { |
| 164 | Device* device = engine->getDevice(); |
| 165 | |
| 166 | if (!engine->isConcatConvSupported(fusion) && !engine->isConcatConv2Supported(fusion)) |
| 167 | { |
| 168 | // Need to split into separate upsample and concat+conv |
| 169 | auto src0Upsample = addUpsample(name + "_upsample0", src0Op); |
| 170 | return addConcatConv(name, src0Upsample, src1Op, activation); |
| 171 | } |
| 172 | |
| 173 | const std::string weightName = name + ".weight"; |
| 174 | const std::string biasName = name + ".bias"; |
| 175 | Ref<Tensor> weight = (*constTensors)[weightName]; |
| 176 | Ref<Tensor> bias = (*constTensors)[biasName]; |
| 177 | |
| 178 | if (weight->getRank() != 4 || bias->getRank() != 1) |
| 179 | throw std::invalid_argument("invalid convolution weight/bias"); |
| 180 | |
| 181 | const int blockC = device->getTensorBlockC(); |
| 182 | |
| 183 | auto src0Alloc = tensorAllocs[src0Op.get()]; |
| 184 | auto src1Alloc = tensorAllocs[src1Op.get()]; |
| 185 | const TensorDesc src0Desc = src0Alloc->desc; |
| 186 | const TensorDesc src1Desc = src1Alloc->desc; |
| 187 | |
| 188 | TensorDims finalWeightDims{round_up(weight->getO(), blockC), |
| 189 | src0Desc.getPaddedC() + src1Desc.getPaddedC(), |
| 190 | weight->getH(), |
| 191 | weight->getW()}; |
| 192 | |
| 193 | TensorDesc finalWeightDesc = {weight->getDims(), |
| 194 | finalWeightDims, |
| 195 | device->getWeightLayout(), |
| 196 | device->getWeightDataType()}; |
| 197 | |
| 198 | TensorDesc finalBiasDesc = {bias->getDims(), |
| 199 | {round_up(bias->getX(), blockC)}, |
| 200 | TensorLayout::x, |
| 201 | device->getTensorDataType()}; |
| 202 | |
| 203 | ConcatConvDesc concatConvDesc{src0Desc, src1Desc, finalWeightDesc, finalBiasDesc, activation, fusion, fastMath}; |
| 204 | |
| 205 | if (engine->isConcatConvSupported(fusion)) |
| 206 | { |
| 207 | auto concatConv = engine->newConcatConv(concatConvDesc); |
| 208 | concatConv->setName(name); |
| 209 | auto dstAlloc = addOp(concatConv, {src0Op, src1Op}, concatConv->getDstDesc(), |
| 210 | concatConv->isPreConcatConv()); |
| 211 | |
| 212 | lazyInits.push_back([=]() |
| 213 | { |
| 214 | concatConv->setSrc(src0Alloc->tensor, src1Alloc->tensor); |
| 215 | concatConv->setDst(dstAlloc->tensor); |
nothing calls this directly
no test coverage detected