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.
docstr: Identify the additional no_op between update_op and train_op if it exists (for certain optimizers).
  
  Args:
      update_op
  
  Returns:
      source_op: the no_op if existed, otherwise the update_op itself.
docstr_tok: ["Identify","the","additional","no_op","between","update_op","and","train_op","if","it","exists","(","for","certain","optimizers",")",".","Args",":","update_op","Returns",":","source_op",":","the","no_op","if","existed",",","otherwise","the","update_op","itself","."]
code: def _get_optimizer_source_op(update_op):
      """
      Identify the additional no_op between update_op and train_op if it exists (for certain optimizers).
  
      Args:
          update_op
  
      Returns:
          source_op: the no_op if existed, otherwise the update_op itself.
      """
      group_deps = [
          op
          for op in get_control_consumers(update_op)
          if "Adam" in op.name
          and "group_deps" in op.name
          and op.type == "NoOp"
      ]
      source_op = group_deps[0] if group_deps else update_op
      return source_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 6 for calling the PSSynchronizer obj's underlying member method code with example usage: obj._get_optimizer_source_op(update_op) and returns: source_op