class_docstr: The abstract sparse optimizer.
  
  Note: dgl sparse optimizer only work with dgl.NodeEmbedding
  
  Parameters
  ----------
  params : list of NodeEmbedding
      The list of NodeEmbeddings.
  lr : float
      The learning rate.
code: def __init__(self, params, lr):
      self._params = params
      self._lr = lr
      self._rank = None
      self._world_size = None
      self._shared_cache = {}
      self._clean_grad = False
      self._opt_meta = {}
      self._comm = None
      self._first_step = True
      self._device = None
      # hold released shared memory to let other process to munmap it first
      # otherwise it will crash the training
      self.shmem_buffer_holder = []
  
      assert len(params) > 0, "Empty parameters"
      # if we are using shared memory for communication
      for emb in params:
          assert isinstance(
              emb, NodeEmbedding
          ), "DGL SparseOptimizer only supports dgl.nn.NodeEmbedding"
  
          if self._rank is None:
              self._rank = emb.rank
              self._world_size = emb.world_size
          else:
              assert (
                  self._rank == emb.rank
              ), "MultiGPU rank for each embedding should be same."
              assert (
                  self._world_size == emb.world_size
              ), "MultiGPU world_size for each embedding should be same."
      assert not self._rank is None
      assert not self._world_size is None
  
imports: import abc
  from abc import abstractmethod
  import torch
  from ...cuda import nccl
  from ...nn.pytorch import NodeEmbedding
  from ...partition import NDArrayPartition
  from ...utils import create_shared_mem_array, gather_pinned_tensor_rows, get_shared_mem_array, pin_memory_inplace, scatter_pinned_tensor_rows
label_desc: Use image node_id 1 to create a new SparseGradOptimizer object from inherited base classes: abc with example: obj = SparseGradOptimizer(params, lr)