'Constructs a Dispatcher.
Args:
data_parallelism: a Parallelism object.
model_parallelism: a Parallelism object.
gates: a list of 1d integer `Tensor`s, one per datashard.
Says which expert to use for each batch element.
Returns:
a DistributedSingleDispatcher'

def __init__(self, data_parallelism, model_parallelism, gates):

    gates = data_parallelism(tf.to_int32, gates)
    self._gates = gates
    self._data_parallelism = data_parallelism
    self._model_parallelism = model_parallelism
    def _PartSizes(gates):
        return tf.unsorted_segment_sum(tf.ones_like(gates), gates, model_parallelism.n)
    part_sizes_by_datashard = data_parallelism(_PartSizes, gates)
    self._part_sizes_by_expert = tf.unstack(tf.stack(part_sizes_by_datashard), num=model_parallelism.n, axis=1)
    def _StitchIndices(gates):
        return tf.dynamic_partition(tf.range(tf.size(gates)), gates, model_parallelism.n)
    self._stitch_indices = data_parallelism(_StitchIndices, gates)
