| 235 | } |
| 236 | |
| 237 | void LoopGrad::AssignorGradOpr::scn_do_execute() { |
| 238 | if (should_fwd()) { |
| 239 | rofwd_execute(); |
| 240 | return; |
| 241 | } |
| 242 | auto&& prev_gsum = m_state->prev_gsum; |
| 243 | auto&& dest = output(0)->dev_tensor(); |
| 244 | if (prev_gsum.empty()) { |
| 245 | // first execution in a loop |
| 246 | |
| 247 | if (m_assignor_grad) { |
| 248 | auto&& src = m_assignor_grad->dev_tensor(); |
| 249 | if (dest.raw_ptr() != src.raw_ptr()) { |
| 250 | dest.copy_from_fixlayout(src); |
| 251 | } else { |
| 252 | mgb_assert(dest.layout().eq_layout(src.layout())); |
| 253 | } |
| 254 | } else { |
| 255 | fill_zero_dev_tensor(dest); |
| 256 | } |
| 257 | return; |
| 258 | } |
| 259 | if (m_assignor_grad) { |
| 260 | auto&& src = m_assignor_grad->dev_tensor(); |
| 261 | opr::Elemwise::perform( |
| 262 | opr::Elemwise::Mode::ADD, const_cast<DeviceTensorND&>(dest), |
| 263 | {src, prev_gsum}, m_state->accum_state.adder); |
| 264 | } else { |
| 265 | dest.copy_from_fixlayout(prev_gsum); |
| 266 | } |
| 267 | m_state->accum_state.reset(); |
| 268 | } |
| 269 | |
| 270 | cg::OperatorNodeBase* LoopGrad::AssignorGradOpr::shallow_copy( |
| 271 | const VarNodeArray& inputs, const OperatorNodeConfig& config) const { |
nothing calls this directly
no test coverage detected