class_docstr: Large-scale distributed sampling face recognition training Module, of course sampling is an option,
  There will be no loss of accuracy in sampling in large-scale identities training tasks, uses only
  8 NVIDIA RTX2080Ti to complete classification tasks with 10 millions of identities, 64 NVIDIA
  RTX2080Ti can complete classification tasks with 100 million of identities.
  
  See the original paper:
  https://arxiv.org/abs/2203.15565
  
  Parameters
  ----------
  symbol: Symbol
      Backbone symbol.
  fc7_model: Object
      Object of margin loss.
  memory_bank: Memory bank Object.
      Object of memory bank, which maintain local class centers and their momentum.
  memory_optimizer: Optimizer object.
      The updater of memory bank, default is sgd optimizer.
  logger:
code: def backward_sample(self, total_feature, label):
      this_rank_classes = int(self.memory_bank.num_sample)
      local_index, unique_sorted_global_label = self.memory_bank.sample(
          label
      )
  
      # Get local index
      _mapping_dict = {}
      local_sampled_class = (
          local_index + self.rank * self.memory_bank.num_local
      )
      global_label_set = set(unique_sorted_global_label)
      for idx, absolute_label in enumerate(local_sampled_class):
          if absolute_label in global_label_set:
              _mapping_dict[absolute_label] = (
                  idx + self.rank * self.memory_bank.num_sample
              )
  
      label_list = list(label.asnumpy())
      mapping_label = []
      for i in range(len(label_list)):
          absolute_label = label_list[i]
          if absolute_label in _mapping_dict.keys():
              mapping_label.append(_mapping_dict[absolute_label])
          else:
              mapping_label.append(-1)
  
      mapping_label = nd.array(mapping_label, dtype=np.int32)
  
      # Get weight
      local_index = nd.array(local_index)
      local_index = self.get_ndarray2(
          self.gpu, "local_index", local_index
      )
      sample_weight, sample_weight_mom = self.memory_bank.get(
          local_index
      )
  
      # Sync to gpu
      if self.memory_bank.gpu:
          _data = self.get_ndarray2(
              self.gpu, "data_%d" % self.rank, total_feature
          )
          _weight = self.get_ndarray2(
              self.gpu, "weight_%d" % self.rank, sample_weight
          )
          _weight_mom = self.get_ndarray2(
              self.gpu, "weight_mom_%d" % self.rank, sample_weight_mom
          )
      else:
          _data = self.get_ndarray2(
              self.gpu, "data_%d" % self.rank, total_feature
          )
          _weight = self.get_ndarray2(
              self.gpu, "weight_%d" % self.rank, sample_weight
          )
          _weight_mom = self.get_ndarray2(
              self.gpu, "weight_mom_%d" % self.rank, sample_weight_mom
          )
  
      # Attach grad
      _data.attach_grad()
      _weight.attach_grad()
  
      # Convert label
      _label = self.get_ndarray2(
          self.gpu, "mapping_label_%d" % self.rank, mapping_label
      )
      _label = _label - int(self.rank * self.memory_bank.num_sample)
      _fc7, _one_hot = self.fc7_model.forward(
          _data, _weight, mapping_label=_label, depth=this_rank_classes
      )
  
      # Sync max
      max_fc7 = nd.max(_fc7, axis=1, keepdims=True)
      max_fc7 = nd.reshape(max_fc7, -1)
  
      total_max_fc7 = self.get_ndarray(
          context=self.gpu,
          name="total_max_fc7",
          shape=(max_fc7.shape[0], self.size),
          dtype="float32",
      )
      total_max_fc7[:] = 0
      total_max_fc7[:, self.rank] = max_fc7
      hvd.allreduce_(total_max_fc7, average=False)
  
      global_max_fc7 = self.get_ndarray(
          context=self.gpu,
          name="global_max_fc7",
          shape=(max_fc7.shape[0], 1),
          dtype="float32",
      )
      nd.max(total_max_fc7, axis=1, keepdims=True, out=global_max_fc7)
  
      # Calculate exp(logits)
      _fc7_grad = nd.broadcast_sub(_fc7, global_max_fc7)
      _fc7_grad = nd.exp(_fc7_grad)
  
      # Calculate sum
      sum_fc7 = nd.sum(_fc7_grad, axis=1, keepdims=True)
      global_sum_fc7 = hvd.allreduce(sum_fc7, average=False)
  
      # Calculate grad
      _fc7_grad = nd.broadcast_div(_fc7_grad, global_sum_fc7)
  
      # Calculate loss
      tmp = _fc7_grad * _one_hot
      tmp = nd.sum(tmp, axis=1, keepdims=True)
      tmp = self.get_ndarray2(self.gpu, "ctx_loss", tmp)
      tmp = hvd.allreduce(tmp, average=False)
      global_loss = -nd.mean(nd.log(tmp + 1e-30))
  
      _fc7_grad = _fc7_grad - _one_hot
  
      # Backward
      _fc7.backward(out_grad=_fc7_grad)
  
      # Update center
      _weight_grad = _weight.grad
      self.memory_optimizer.update(
          weight=_weight,
          grad=_weight_grad,
          state=_weight_mom,
          learning_rate=self.memory_lr,
      )
      if self.memory_bank.gpu:
          self.memory_bank.set(
              index=local_index,
              updated_weight=_weight,
              updated_weight_mom=_weight_mom,
          )
      else:
          self.memory_bank.set(
              index=local_index,
              updated_weight=self.get_ndarray2(
                  mx.cpu(), "cpu_weight_%d" % self.rank, _weight
              ),
              updated_weight_mom=self.get_ndarray2(
                  mx.cpu(), "cpu_weight_mom_%d" % self.rank, _weight_mom
              ),
          )
      return _data.grad, global_loss
  
imports: import logging
  import warnings
  from collections import namedtuple
  import horovod.mxnet
  import mxnet
  import mxnet.ndarray
  import numpy
  from default import config
  from optimizer import DistributedOptimizer
label_desc: Use image node_id 18 for calling the SampleDistributeModule obj's underlying member method code with example usage: obj.backward_sample(total_feature, label) and returns: _data,  global_loss