class_docstr: PS Synchronizer.
  
  Synchronizes gradient updates using a Parameter Server.
  
  For in-graph synchronization, this just aggregates gradients on a worker's CPU.
  
  For between-graph synchronization, this aggregates gradients on a pre-defined
  (defined in the Strategy) parameter server.
  
  To keep this gradient aggregation in sync, the chief gives each worker a token
  for each variable for the workers to mark when their variable update is complete.
code: def _get_accumulation_ops(
      graph_item, gradient, target, num_accum_required
  ):
      def _get_accum_apply_and_agg_grad(
          var_op, grad, indices, dense_shape
      ):
          if indices is None:
              tensor = variable_utils.get_read_var_tensor(var_op)
              grad_accum = data_flow_ops.ConditionalAccumulator(
                  grad.dtype,
                  shape=tensor.get_shape(),
                  shared_name=var_op.name + "/grad_accum",
              )
              # Get a copy of consumers list before creating accum_apply_op
              grad_consumers = list(grad.consumers())
              accum_apply_op = grad_accum.apply_grad(
                  grad,
                  local_step=MAX_INT64,
                  name=grad.op.name + "_accum_apply_grad",
              )
              agg_grad = grad_accum.take_grad(
                  num_accum_required, name=var_op.name + "_take_grad"
              )
              update_consumers(grad_consumers, grad, agg_grad)
              update_control_consumers(
                  get_control_consumers(grad.op), grad.op, agg_grad.op
              )
          else:
              grad_indexed_slices = ops.IndexedSlices(
                  values=grad, indices=indices, dense_shape=dense_shape
              )
              grad_accum = data_flow_ops.SparseConditionalAccumulator(
                  grad.dtype,
                  shape=grad.shape,
                  shared_name=var_op.name + "/grad_accum",
              )
              # Get a copy of consumers list before creating accum_apply_op
              indices_consumers = list(indices.consumers())
              grad_consumers = list(grad.consumers())
              accum_apply_op = grad_accum.apply_indexed_slices_grad(
                  grad_indexed_slices,
                  local_step=MAX_INT64,
                  name=grad.op.name + "_accum_apply_grad",
              )
              agg_grad = grad_accum.take_indexed_slices_grad(
                  num_accum_required, name=var_op.name + "_take_grad"
              )
              agg_indices = agg_grad.indices
              if indices.dtype != agg_grad.indices.dtype:
                  agg_indices = math_ops.cast(
                      agg_grad.indices, indices.dtype
                  )
              agg_grad = ops.IndexedSlices(
                  values=agg_grad.values,
                  indices=agg_indices,
                  dense_shape=agg_grad.dense_shape,
              )
              assert isinstance(agg_grad, ops.IndexedSlices)
              update_consumers(
                  indices_consumers, indices, agg_grad.indices
              )
              update_consumers(grad_consumers, grad, agg_grad.values)
              update_control_consumers(
                  get_control_consumers(indices.op),
                  indices.op,
                  agg_grad.indices.op,
              )
              update_control_consumers(
                  get_control_consumers(grad.op),
                  grad.op,
                  agg_grad.values.op,
              )
          return accum_apply_op, agg_grad
  
      # Aggregate gradients from different workers using ConditionalAccumulator.
      # var_op_to_agg_grad and var_op_to_accum_apply_op are updated.
      var_op_to_agg_grad = {}
      var_op_to_accum_apply_op = {}
  
      if target.op not in graph_item.trainable_var_op_to_var:
          logging.debug(
              "Gradient for non-trainable variable %s is created, "
              "do not insert accumulator for aggregating this gradient"
              % target.op.name
          )
          return {}, {}
  
      var_op = target.op
      if isinstance(gradient, ops.Tensor):
          grad = gradient
          indices = None
          dense_shape = None
      else:
          grad = gradient.values
          indices = gradient.indices
          dense_shape = gradient.dense_shape
      with ops.device(var_op.device), ops.name_scope(""):
          accum_apply_op, agg_grad = _get_accum_apply_and_agg_grad(
              var_op, grad, indices, dense_shape
          )
      if indices is None:
          var_op_to_agg_grad[var_op] = (None, agg_grad)
      else:
          var_op_to_agg_grad[var_op] = (
              agg_grad.indices,
              agg_grad.values,
          )
      var_op_to_accum_apply_op[var_op] = accum_apply_op
      return var_op_to_agg_grad, var_op_to_accum_apply_op
  
imports: from functools import partial
  from typing import List
  from tensorflow.python import ops
  from tensorflow.python.framework import device_spec, dtypes, constant_op
  from tensorflow.python.platform import tf_logging
  from tensorflow.python.ops import math_ops, data_flow_ops, gen_control_flow_ops, control_flow_ops, gen_math_ops, gen_array_ops
  from autodist.const import MAX_INT64, AUTODIST_PREFIX
  from autodist.kernel.common import utils, variable_utils
  from autodist.kernel.common.op_info import UPDATE_OP_VAR_POS
  from autodist.kernel.common.proxy_variable import ProxyVariable
  from autodist.kernel.common.utils import get_op_name, get_consumers, get_ancestors, traverse, update_consumers, update_control_consumers, replica_prefix, strip_replica_prefix, get_control_consumers, remove_from_control_consumers, get_index_from_tensor_name, update_colocation_group
  from autodist.kernel.common.variable_utils import get_read_var_ops
  from autodist.kernel.synchronization.synchronizer import Synchronizer
  from autodist.proto import synchronizers_pb2
label_desc: Use image node_id 15 for calling the PSSynchronizer obj's underlying member method code with example usage: obj._get_accumulation_ops(graph_item, gradient, target, num_accum_required) and returns: var_op_to_agg_grad,  var_op_to_accum_apply_op, accum_apply_op,  agg_grad, dict,  dict