| 107 | REGISTER_GRADIENT_OP("DynamicPartition", DynamicPartitionGrad); |
| 108 | |
| 109 | Status DynamicStitchGrad(const Scope& scope, const Operation& op, |
| 110 | const std::vector<Output>& grad_inputs, |
| 111 | std::vector<Output>* grad_outputs) { |
| 112 | // Running example: |
| 113 | // indices = {2, [1, 0]} |
| 114 | // data = {[d_1, d_2], [[d_3, d_4], [d_5, d_6]]} |
| 115 | // out = [[d_5, d_6], [d_3, d_4], [d_1, d_2]] |
| 116 | // grad = [[g_1, g_2], [g_3, g_4], [g_5, g_6]] |
| 117 | |
| 118 | // indices and data are two equal-sized lists passed |
| 119 | // into DynamicStitch. |
| 120 | // num_values = 2 |
| 121 | int32 num_values = op.num_inputs() / 2; |
| 122 | |
| 123 | // Stop propagation along the indices list |
| 124 | for (int32 i = 0; i < num_values; i++) { |
| 125 | grad_outputs->push_back(NoGradient()); |
| 126 | } |
| 127 | |
| 128 | // DynamicStitch shuffles its data to the output (using items in |
| 129 | // indices) so the gradient propagated to a given data input simply |
| 130 | // selects the gradient for its output position. |
| 131 | for (int32 i = 0; i < num_values; i++) { |
| 132 | // index has the destination positions for the i'th data |
| 133 | // element. We cast it into an int32 if necessary, so we can use |
| 134 | // it from a Gather op. |
| 135 | // i = 0: index = 2 |
| 136 | // i = 1: index = [1, 0] |
| 137 | auto index = op.input(i); |
| 138 | if (index.type() != DT_INT32) { |
| 139 | index = Cast(scope, index, DT_INT32); |
| 140 | } |
| 141 | // Gather the index specified locations in the gradient and |
| 142 | // propagate it as the gradient for the i'th data item. |
| 143 | // i = 0: gather(grad, 2) = [g_5, g_6] |
| 144 | // i = 1: gather(grad, [1, 0]) = [[g_3, g_4], [g_1, g_2]] |
| 145 | grad_outputs->push_back(Gather(scope, grad_inputs[0], index)); |
| 146 | } |
| 147 | |
| 148 | return scope.status(); |
| 149 | } |
| 150 | REGISTER_GRADIENT_OP("DynamicStitch", DynamicStitchGrad); |
| 151 | REGISTER_GRADIENT_OP("DynamicStitchFast", DynamicStitchGrad); |
| 152 | REGISTER_GRADIENT_OP("ParallelDynamicStitch", DynamicStitchGrad); |
nothing calls this directly
no test coverage detected