Create an op that groups multiple operations. When this op finishes, all ops in `inputs` have finished. This op has no output. See also `tf.tuple` and `tf.control_dependencies`. Args: *inputs: Zero or more tensors to group. name: A name for this operation (optional). Returns:
(*inputs, **kwargs)
| 2849 | # TODO(touts): Accept "inputs" as a list. |
| 2850 | @tf_export("group") |
| 2851 | def group(*inputs, **kwargs): |
| 2852 | """Create an op that groups multiple operations. |
| 2853 | |
| 2854 | When this op finishes, all ops in `inputs` have finished. This op has no |
| 2855 | output. |
| 2856 | |
| 2857 | See also `tf.tuple` and |
| 2858 | `tf.control_dependencies`. |
| 2859 | |
| 2860 | Args: |
| 2861 | *inputs: Zero or more tensors to group. |
| 2862 | name: A name for this operation (optional). |
| 2863 | |
| 2864 | Returns: |
| 2865 | An Operation that executes all its inputs. |
| 2866 | |
| 2867 | Raises: |
| 2868 | ValueError: If an unknown keyword argument is provided. |
| 2869 | """ |
| 2870 | if context.executing_eagerly(): |
| 2871 | return None |
| 2872 | name = kwargs.pop("name", None) |
| 2873 | if kwargs: |
| 2874 | raise ValueError("Unknown keyword arguments: " + ", ".join(kwargs.keys())) |
| 2875 | with ops.name_scope(name, "group_deps", inputs) as name: |
| 2876 | # Grouping no inputs means do nothing |
| 2877 | if not inputs: |
| 2878 | return no_op(name=name) |
| 2879 | |
| 2880 | # Sorts *inputs according to their devices. |
| 2881 | ops_on_device = {} # device -> operations specified on the device. |
| 2882 | for inp in nest.flatten(inputs, expand_composites=True): |
| 2883 | if not hasattr(inp, "device"): |
| 2884 | raise TypeError("Expected tf.group() expected Tensor arguments not " |
| 2885 | "'%s' with type '%s'" % (inp, type(inp))) |
| 2886 | dev = inp.device |
| 2887 | if dev in ops_on_device: |
| 2888 | ops_on_device[dev].append(inp) |
| 2889 | else: |
| 2890 | ops_on_device[dev] = [inp] |
| 2891 | if len(ops_on_device) == 1: |
| 2892 | # 1-level tree. The root node is the returned NoOp node. |
| 2893 | (dev, deps), = ops_on_device.items() |
| 2894 | return _GroupControlDeps(dev, deps, name=name) |
| 2895 | |
| 2896 | # 2-level tree. The root node is the returned NoOp node. |
| 2897 | # deps contains 1 NoOp node for each device. |
| 2898 | deps = [] |
| 2899 | |
| 2900 | def device_key(dev): |
| 2901 | """A sort key that allows None to be compared to strings.""" |
| 2902 | return "" if dev is None else dev |
| 2903 | |
| 2904 | for dev in sorted(ops_on_device, key=device_key): |
| 2905 | deps.append(_GroupControlDeps(dev, ops_on_device[dev])) |
| 2906 | |
| 2907 | with ops.control_dependencies(deps): |
| 2908 | return no_op(name=name) |
no test coverage detected