| 288 | class GeometryTensorArrayScatter : public GeometryComputer { |
| 289 | public: |
| 290 | virtual bool onCompute(const Op* op, const std::vector<Tensor*>& inputs, const std::vector<Tensor*>& outputs, |
| 291 | Context& context, CommandBuffer& res) const override { |
| 292 | auto tensorArrayInput = inputs[3]; |
| 293 | auto inDes = TensorUtils::getDescribe(tensorArrayInput); |
| 294 | if (inDes->tensorArrayAttr == nullptr) { |
| 295 | return false; |
| 296 | } |
| 297 | int oldSize = inDes->tensorArrayAttr->arraySize; |
| 298 | auto output = outputs[0]; |
| 299 | int elemSize = getElemSize(output, 0).second; |
| 300 | auto indicesTensor = inputs[1]; |
| 301 | // tag index write or not |
| 302 | std::vector<bool> isWrite(oldSize, false); |
| 303 | // write index |
| 304 | std::vector<int> indices(indicesTensor->elementSize()); |
| 305 | // not write index |
| 306 | std::vector<int> remains; |
| 307 | for (int i = 0; i < indices.size(); i++) { |
| 308 | indices[i] = indicesTensor->host<int>()[i]; |
| 309 | if (i < oldSize) { |
| 310 | isWrite[i] = true; |
| 311 | } |
| 312 | } |
| 313 | for (int i = 0; i < oldSize; i++) { |
| 314 | if (!isWrite[i]) { |
| 315 | remains.push_back(i); |
| 316 | } |
| 317 | } |
| 318 | auto outputDes = TensorUtils::getDescribe(output); |
| 319 | outputDes->memoryType = Tensor::InsideDescribe::MEMORY_VIRTUAL; |
| 320 | outputDes->regions.resize(indices.size() + remains.size()); |
| 321 | // write value by indices |
| 322 | for (int i = 0; i < indices.size(); i++) { |
| 323 | MNN_ASSERT(indices[i] < outputDes->tensorArrayAttr->arraySize); |
| 324 | auto& reg = outputDes->regions[i]; |
| 325 | reg.origin = inputs[2]; |
| 326 | reg.src.offset = i * elemSize; |
| 327 | reg.src.stride[0] = 1; |
| 328 | reg.src.stride[1] = 1; |
| 329 | reg.src.stride[2] = 1; |
| 330 | reg.dst.offset = indices[i] * elemSize; |
| 331 | reg.dst.stride[0] = 1; |
| 332 | reg.dst.stride[1] = 1; |
| 333 | reg.dst.stride[2] = 1; |
| 334 | reg.size[0] = elemSize; |
| 335 | reg.size[1] = 1; |
| 336 | reg.size[2] = 1; |
| 337 | } |
| 338 | if (remains.empty()) { |
| 339 | return true; |
| 340 | } |
| 341 | // first write data, set zero |
| 342 | bool firstWrite = isFirstWrite(inDes); |
| 343 | if (firstWrite) { |
| 344 | auto type = tensorArrayInput->getType(); |
| 345 | auto zeroConst = context.allocConst(op, {}, type); |
| 346 | if (type == halide_type_of<float>()) { |
| 347 | zeroConst->host<float>()[0] = 0.0; |
nothing calls this directly
no test coverage detected