| 334 | } |
| 335 | |
| 336 | Status SymbolicGradientBuilder::Compute() { |
| 337 | // Initialize backprops. |
| 338 | InitBackprop(); |
| 339 | |
| 340 | // Backward propagation. |
| 341 | gtl::InlinedVector<NodeOut, 8> dy; |
| 342 | while (!ready_.empty()) { |
| 343 | // n has collected all gradients. |
| 344 | Node* n = ready_.front(); |
| 345 | ready_.pop_front(); |
| 346 | |
| 347 | // "n" has num_x inputs and num_y outputs. |
| 348 | const int num_x = n->num_inputs(); |
| 349 | const int num_y = n->num_outputs(); |
| 350 | |
| 351 | auto iter = stop_nodes_.find(n->id()); |
| 352 | if (iter != stop_nodes_.end()) { |
| 353 | // Stop backprop. |
| 354 | // TODO(andydavis) Support stop nodes with more than one output. |
| 355 | CHECK_EQ(1, num_y); |
| 356 | continue; |
| 357 | } |
| 358 | |
| 359 | // dy[i] is the sum of i-th output's backpropped gradients. |
| 360 | dy.clear(); |
| 361 | dy.resize(num_y, {nullptr, 0}); |
| 362 | for (int i = 0; i < num_y; ++i) { |
| 363 | dy[i] = SumGradients({n, i}); |
| 364 | } |
| 365 | |
| 366 | if (IsPrimitiveOpWithNoGrad(n->type_string())) { |
| 367 | // No grad defined for this op: Backprop zeros along the in edges. |
| 368 | for (const Edge* e : n->in_edges()) { |
| 369 | if (e->IsControlEdge()) continue; |
| 370 | BackpropZerosAlongEdge({e->src(), e->src_output()}); |
| 371 | } |
| 372 | continue; |
| 373 | } |
| 374 | |
| 375 | // Adds a gradient node with num_x + num_y inputs and num_x |
| 376 | // outputs. |
| 377 | // TODO(andydavis) Support primitive gradient ops. |
| 378 | Node* grad = AddSymGrad(graph_, n, dy); |
| 379 | for (const Edge* e : n->in_edges()) { |
| 380 | if (e->IsControlEdge()) continue; |
| 381 | graph_->AddEdge(e->src(), e->src_output(), grad, e->dst_input()); |
| 382 | } |
| 383 | for (int i = 0; i < num_y; ++i) { |
| 384 | graph_->AddEdge(dy[i].node, dy[i].index, grad, num_x + i); |
| 385 | } |
| 386 | |
| 387 | // Backprops along the in edges. |
| 388 | for (const Edge* e : n->in_edges()) { |
| 389 | if (e->IsControlEdge()) continue; |
| 390 | BackpropAlongEdge({grad, e->dst_input()}, {e->src(), e->src_output()}); |
| 391 | } |
| 392 | } |
| 393 |
no test coverage detected