| 17 | class GeometryLRN : public GeometryComputer { |
| 18 | public: |
| 19 | bool computeForNormalize(const Op* op, const std::vector<Tensor*>& inputs, const std::vector<Tensor*>& outputs, |
| 20 | Context& context, CommandBuffer& res) const { |
| 21 | auto normalize = op->main_as_Normalize(); |
| 22 | auto mAcrossSpatial = normalize->acrossSpatial(); |
| 23 | auto mChannelShared = normalize->channelShared(); |
| 24 | Tensor* eps = nullptr; |
| 25 | Tensor* scale = nullptr; |
| 26 | auto cache = context.searchConst(op); |
| 27 | if (!cache.empty()) { |
| 28 | eps = cache[0].get(); |
| 29 | scale = cache[1].get(); |
| 30 | } else { |
| 31 | auto mEps = normalize->eps(); |
| 32 | auto epsT = context.allocConst(op, {}, halide_type_of<float>()); |
| 33 | epsT->host<float>()[0] = mEps; |
| 34 | eps = epsT.get(); |
| 35 | auto mScale = context.allocConst(op, {1, (int)normalize->scale()->size(), 1}, halide_type_of<float>()); |
| 36 | ::memcpy(mScale->host<float>(), normalize->scale()->data(), normalize->scale()->size() * sizeof(float)); |
| 37 | scale = mScale.get(); |
| 38 | } |
| 39 | auto inputTensor = inputs[0]; |
| 40 | // Across channel |
| 41 | int inside = inputTensor->width() * inputTensor->height(); |
| 42 | int axis = inputTensor->channel(); |
| 43 | int outside = inputTensor->batch(); |
| 44 | |
| 45 | { |
| 46 | // 1, axis, 1 -> outside, axis, inside |
| 47 | std::shared_ptr<Tensor> broadCastScale(Tensor::createDevice<float>({outside, axis, inside}, Tensor::CAFFE)); |
| 48 | res.extras.emplace_back(broadCastScale); |
| 49 | auto des = TensorUtils::getDescribe(broadCastScale.get()); |
| 50 | des->memoryType = Tensor::InsideDescribe::MEMORY_VIRTUAL; |
| 51 | des->regions.resize(1); |
| 52 | auto& reg = des->regions[0]; |
| 53 | reg.size[0] = outside; |
| 54 | reg.size[1] = axis; |
| 55 | reg.size[2] = inside; |
| 56 | reg.src.offset = 0; |
| 57 | reg.src.stride[0] = 0; |
| 58 | reg.src.stride[1] = 1; |
| 59 | reg.src.stride[2] = 0; |
| 60 | reg.dst.offset = 0; |
| 61 | reg.dst.stride[0] = axis * inside; |
| 62 | reg.dst.stride[1] = inside; |
| 63 | reg.dst.stride[2] = 1; |
| 64 | reg.origin = scale; |
| 65 | scale = broadCastScale.get(); |
| 66 | } |
| 67 | |
| 68 | // Across Spatial |
| 69 | if (mAcrossSpatial) { |
| 70 | inside = 1; |
| 71 | axis = inputTensor->width() * inputTensor->height() * inputTensor->channel(); |
| 72 | } |
| 73 | std::shared_ptr<Tensor> inputRaw(Tensor::createDevice<float>({outside, axis, inside}, Tensor::CAFFE)); |
| 74 | res.extras.emplace_back(inputRaw); |
| 75 | std::shared_ptr<Tensor> inputRawSquare(Tensor::createDevice<float>({outside, axis, inside}, Tensor::CAFFE)); |
| 76 | res.extras.emplace_back(inputRawSquare); |