MCPcopy Create free account
hub / github.com/MegEngine/MegEngine / subtensor_grad_rule

Function subtensor_grad_rule

imperative/python/src/grad_override.cpp:316–378  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

314}
315
316std::optional<ValueRefList> subtensor_grad_rule(
317 const OpDef& op, Span<ValueRef> inputs, Span<bool> inputs_require_grad,
318 CustomBackward& backward) {
319 auto&& subtensor = op.cast_final_safe<Subtensor>();
320 auto&& grad_op = SetSubtensor::make(subtensor.items);
321 SmallVector<ValueRef> inputs2;
322 if (inputs_require_grad[0]) {
323 inputs2.push_back(get_shape(inputs[0]));
324 for (size_t i = 1; i < inputs.size(); ++i) {
325 inputs2.push_back(inputs[i]);
326 }
327 }
328 CompNodeValue::ref_t device = inputs[0].device();
329 auto get_subtensor_index = [&](int idx) {
330 HostTensorStorage storage(*device);
331 storage.ensure_size(dtype::Int32().size());
332 auto* ptr = reinterpret_cast<dt_int32*>(storage.ptr());
333 ptr[0] = idx;
334 return imperative::apply(
335 CreateTensor(
336 CreateTensor::Unique, *device, dtype::Int32(), ValueShape({1})),
337 HostStorage::make(storage))[0];
338 };
339 auto slice_items = subtensor.slice_items;
340 auto items = subtensor.items;
341 for (int i = 0; i < slice_items.size(); i++) {
342 auto&& [axis, b_flag, e_flag, s_flag, idx_flag] = items[i];
343 auto&& [b_val, e_val, s_val, ax_val] = slice_items[i];
344 if (b_flag) {
345 inputs2.push_back(get_subtensor_index(b_val));
346 };
347 if (e_flag) {
348 inputs2.push_back(get_subtensor_index(e_val));
349 };
350 if (s_flag) {
351 inputs2.push_back(get_subtensor_index(s_val));
352 };
353 if (idx_flag) {
354 inputs2.push_back(get_subtensor_index(ax_val));
355 };
356 };
357 auto maker = CustomGradMaker(backward, inputs.size());
358 maker.output_size(1).output_captured(0, false);
359 maker.backward([inputs = std::move(inputs2),
360 grad_op_ = std::move(grad_op)](Span<ValueRef> grads) {
361 mgb_assert(grads.size() == 1);
362 ValueRef grad = grads[0];
363 SmallVector<ValueRef> ret(1);
364 if (grad && inputs[0]) {
365 ValueRefList args_(inputs.size() + 1);
366 auto&& zeros = make_empty_tensor(grad.device(), inputs[0], grad.dtype());
367 args_[0] = zeros;
368 args_[1] = grad;
369 for (size_t i = 1; i < inputs.size(); ++i) {
370 args_[i + 1] = inputs[i];
371 }
372 ret[0] = imperative::apply(ApplyOp(*grad_op_), args_)[0];
373 }

Callers

nothing calls this directly

Calls 15

get_shapeFunction · 0.85
CreateTensorClass · 0.85
ValueShapeClass · 0.85
CustomGradMakerClass · 0.85
make_empty_tensorFunction · 0.85
output_sizeMethod · 0.80
makeFunction · 0.50
applyFunction · 0.50
ApplyOpClass · 0.50
push_backMethod · 0.45
sizeMethod · 0.45
deviceMethod · 0.45

Tested by

no test coverage detected