Generates gradient While operator
(op, g_output)
| 199 | |
| 200 | |
| 201 | def gen_while_gradient(op, g_output): |
| 202 | """ |
| 203 | Generates gradient While operator |
| 204 | """ |
| 205 | from caffe2.python.core import BlobReference |
| 206 | assert op.type == "While", "Expected While op" |
| 207 | assert len(op.input) > 0, "Expected at least one input in While op" |
| 208 | |
| 209 | assert len(op.output) == len(g_output), \ |
| 210 | "Different number of gradient blobs and While op outputs" |
| 211 | |
| 212 | grad_ops, deduped_g_output = dedupe_g_output(op, g_output) |
| 213 | g_output = deduped_g_output |
| 214 | |
| 215 | init_grad_map = {} |
| 216 | op_output = [str(o) for o in op.output] |
| 217 | for output_name, grad_output_name in zip(op_output, g_output): |
| 218 | if grad_output_name: |
| 219 | init_grad_map[BlobReference(output_name)] = \ |
| 220 | BlobReference(grad_output_name) |
| 221 | assert len(init_grad_map) > 0, "Empty initial gradient map for While op" |
| 222 | |
| 223 | loop_net = _get_net_argument(op, "loop_net") |
| 224 | assert loop_net, "Expected loop subnet in While op" |
| 225 | assert len(loop_net.op) == 1 and loop_net.op[0].type == "Do", \ |
| 226 | "Gradient While op requires single Do op as a loop body" |
| 227 | do_op = loop_net.op[0] |
| 228 | do_args = _get_do_arguments(do_op) |
| 229 | assert "reuse_workspace" not in do_args or not do_args["reuse_workspace"], \ |
| 230 | "Gradient While op requires Do loop body op without reuse_workspace set" |
| 231 | |
| 232 | assert len(do_op.output) > 0, "Expected Do op with at least one output" |
| 233 | workspace_blob = do_op.output[-1] |
| 234 | |
| 235 | loop_grad_net, loop_grad_map, loop_input_names, loop_output_names = \ |
| 236 | _gen_subnet_gradient(loop_net, init_grad_map) |
| 237 | assert loop_grad_net, "Failed to get gradient net for loop body in While op" |
| 238 | |
| 239 | grad_ops += _prepare_gradient_while_ops( |
| 240 | fwd_op=op, |
| 241 | input_names=loop_input_names, |
| 242 | output_names=loop_output_names, |
| 243 | loop_grad_net=loop_grad_net, |
| 244 | workspace_blob=workspace_blob, |
| 245 | init_grad_map=init_grad_map, |
| 246 | loop_grad_map=loop_grad_map) |
| 247 | |
| 248 | op_input = [str(i) for i in op.input] |
| 249 | g_input = [loop_grad_map.get(i, None) for i in op_input] |
| 250 | return grad_ops, g_input |
| 251 | |
| 252 | |
| 253 | # Constructs gradient While op, arguments: |
nothing calls this directly
no test coverage detected
searching dependent graphs…