Injecting Copy functions between device within a net. Users can provide a net with part of operators using different device_options. This method will automatically create a new net with Copy ops inserted in it. Inputs: blob_to_device: If not None, it is a map of blobs and the
(net, blob_to_device=None, blob_remap=None,
placeHolderOps=None)
| 2459 | |
| 2460 | |
| 2461 | def InjectCrossDeviceCopies(net, blob_to_device=None, blob_remap=None, |
| 2462 | placeHolderOps=None): |
| 2463 | ''' |
| 2464 | Injecting Copy functions between device within a net. Users can provide |
| 2465 | a net with part of operators using different device_options. This method |
| 2466 | will automatically create a new net with Copy ops inserted in it. |
| 2467 | |
| 2468 | Inputs: |
| 2469 | blob_to_device: If not None, it is a map of blobs and their device locations. |
| 2470 | blob_remap: If not None, it is a map from a pair (blob, device) to |
| 2471 | the name of the blob in the given device. Blobs found in this |
| 2472 | map are assumed to be cached and don't need to be copied. |
| 2473 | Outputs: |
| 2474 | new_net: A new net with CopyCPUToGPU inserted with correct device option |
| 2475 | |
| 2476 | required_external_to_device: |
| 2477 | A mapping between unresolved external inputs and their |
| 2478 | required device options. |
| 2479 | Assumptions: |
| 2480 | 1. every external inputs of this net is already in blob_to_device! |
| 2481 | 2. if not, this function will use net device option |
| 2482 | 3. InferOpBlobDevices might fail to get the correct inference for ops like |
| 2483 | EnsureCPUOutput that could take in input from multiple places. |
| 2484 | ''' |
| 2485 | new_net = net.Clone(net._net.name + '_cross_device', keep_schema=True) |
| 2486 | del new_net._net.op[:] |
| 2487 | if blob_to_device is None: |
| 2488 | blob_to_device = {} |
| 2489 | # remapping of input blobs for each op. |
| 2490 | if blob_remap is None: |
| 2491 | blob_remap = {} |
| 2492 | temp_remap = {} |
| 2493 | net_option = net._net.device_option or caffe2_pb2.DeviceOption() |
| 2494 | |
| 2495 | # if external_inputs have device remappings generated by previous nets, |
| 2496 | # then add those remappings as external inputs as well. |
| 2497 | all_remaps = defaultdict(list) |
| 2498 | for entry, mapped_blob in blob_remap.items(): |
| 2499 | all_remaps[entry.blob].append(mapped_blob) |
| 2500 | mapped_external_inputs = [] |
| 2501 | for input in new_net._net.external_input: |
| 2502 | mapped_external_inputs.extend(all_remaps.get(input) or []) |
| 2503 | new_net._net.external_input.extend(mapped_external_inputs) |
| 2504 | |
| 2505 | for op in net._net.op: |
| 2506 | temp_remap.clear() |
| 2507 | # Get where inputs and outputs should be. If it is a Placeholder |
| 2508 | # (i.e. fake) op, then set op's device as blob's devices. |
| 2509 | input_dev = None |
| 2510 | output_dev = None |
| 2511 | if placeHolderOps is not None and op.type in placeHolderOps: |
| 2512 | input_dev, output_dev = InferOpDeviceAsBlobDevices(op) |
| 2513 | else: |
| 2514 | input_dev, output_dev = InferOpBlobDevices(op) |
| 2515 | |
| 2516 | for dev, input in zip(input_dev, op.input): |
| 2517 | assert net.BlobIsDefined(input), \ |
| 2518 | "input {} should be defined in the net.".format(input) |
no test coverage detected
searching dependent graphs…