class_docstr: Initialize the Lightseq Transformer Decoder Layer.
  
  Static variable:
      layer_id: The layer-index counter starting from 0 and incrementing by 1 every time a layer object is instantiated,
      e.g. if a model has 24 transformer layers, layer_id goes from 0 to 23.
  Arguments:
      config: An object of LSTransformerDecoderLayer config, see get_config
  
      initial_weights: Optional: Only used for unit test
  
      initial_biases: Optional: Only used for unit test
class_docstr_tok: ["Initialize","the","Lightseq","Transformer","Decoder","Layer",".","Static","variable",":","layer_id",":","The","layer-index","counter","starting","from","0","and","incrementing","by","1","every","time","a","layer","object","is","instantiated",",","e.g",".","if","a","model","has","24","transformer","layers",",","layer_id","goes","from","0","to","23",".","Arguments",":","config",":","An","object","of","LSTransformerDecoderLayer","config",",","see","get_config","initial_weights",":","Optional",":","Only","used","for","unit","test","initial_biases",":","Optional",":","Only","used","for","unit","test"]
docstr: decoder_states, [batch_size, trg_len, hidden_size] or [batch_size * beam_size, 1, hidden_size]
  encoder_out, [src_len, batch_size, hidden_size]
  encoder_padding_mask, [batch_size, src_len], 0 for non-pad, 1 for padding
  cache, dict, {"dec_self_k": [batch*beam, nh, step, hd],
                "dec_self_v": [batch*beam, nh, step, hd],
                "encdec_kv": [n_dec_layer * 2, batch_size, nhead, src_seq_len, head_dim]
                }
docstr_tok: ["decoder_states",",","[","batch_size",",","trg_len",",","hidden_size","]","or","[","batch_size","*","beam_size",",","1",",","hidden_size","]","encoder_out",",","[","src_len",",","batch_size",",","hidden_size","]","encoder_padding_mask",",","[","batch_size",",","src_len","]",",","0","for","non-pad",",","1","for","padding","cache",",","dict",",","{","``","dec_self_k","''",":","[","batch","*","beam",",","nh",",","step",",","hd","]",",","``","dec_self_v","''",":","[","batch","*","beam",",","nh",",","step",",","hd","]",",","``","encdec_kv","''",":","[","n_dec_layer","*","2",",","batch_size",",","nhead",",","src_seq_len",",","head_dim","]","}"]
code: def forward(
      self,
      decoder_states,
      encoder_out,
      encoder_padding_mask,
      cache=None,
      **kwargs,
  ):
      """
      decoder_states, [batch_size, trg_len, hidden_size] or [batch_size * beam_size, 1, hidden_size]
      encoder_out, [src_len, batch_size, hidden_size]
      encoder_padding_mask, [batch_size, src_len], 0 for non-pad, 1 for padding
      cache, dict, {"dec_self_k": [batch*beam, nh, step, hd],
                    "dec_self_v": [batch*beam, nh, step, hd],
                    "encdec_kv": [n_dec_layer * 2, batch_size, nhead, src_seq_len, head_dim]
                    }
      """
      self.config.training = self.training
      self.config.is_grad_enabled = torch.is_grad_enabled()
      self.config.quant_mode = self.quant_mode
  
      decoder_states = decoder_states.contiguous()
      # [s, b, h] -> [b, s, h]
      encoder_out = encoder_out.transpose(0, 1).contiguous()
      encoder_padding_mask = (
          (encoder_padding_mask * -1e8)
          .type_as(decoder_states)
          .contiguous()
      )
  
      if self.config.fp16 and self.para.dtype != torch.half:
          if hasattr(self, "para_16"):
              self.para_16.copy_(self.para.to(torch.half))
          else:
              self.register_buffer(
                  "para_16", self.para.clone().detach().half()
              )
  
      if self.config.fp16:
          decoder_states = decoder_states.to(torch.half)
          encoder_out = encoder_out.to(torch.half)
          encoder_padding_mask = encoder_padding_mask.to(torch.half)
  
      self.__assign_layer_weight_grad()
      cache_list = []
      if cache is not None:
          # predict
          batch_beams = decoder_states.shape[0]
          if cache:
              # non-empty dict, step 1-n
              step = cache["dec_self_k"].shape[2]
              # Thanks to fengjiangtao@bytedance.com
              # for helping us find this bug.
              cache_list = [
                  cache["dec_self_k"].contiguous(),
                  cache["dec_self_v"].contiguous(),
              ]
          else:
              # empty dict, step 0
              step = 0
          if self.config.layer_id == 0:
              if step == 0:
                  shape = (
                      self.config.nlayer * 2,
                      encoder_out.shape[0],
                      encoder_out.shape[1] * self.config.hidden_size,
                  )
                  encdec_kv = torch.zeros(
                      shape,
                      dtype=decoder_states.dtype,
                      device=decoder_states.device,
                  ).contiguous()
                  cache["encdec_kv"] = encdec_kv
              cache_list.append(cache["encdec_kv"])
          head_dim = int(self.config.hidden_size / self.config.nhead)
          shape = (batch_beams, self.config.nhead, step + 1, head_dim)
          new_k = torch.zeros(
              shape,
              dtype=decoder_states.dtype,
              device=decoder_states.device,
          ).contiguous()
          new_v = torch.zeros(
              shape,
              dtype=decoder_states.dtype,
              device=decoder_states.device,
          ).contiguous()
          cache_list = [new_k, new_v] + cache_list
          cache["dec_self_k"] = new_k
          cache["dec_self_v"] = new_v
          self.config.training = False
      bs, sl, dim = decoder_states.size()
      if bs * sl > self.config.max_batch_tokens:
          raise ValueError(
              f"Batch token numbers {bs * sl} exceeds the limit"
              f" {self.config.max_batch_tokens}."
          )
      if sl > self.config.max_seq_len:
          raise ValueError(
              f"Sequence length {sl} exceeds the limit {self.config.max_seq_len}."
          )
      if len(encoder_padding_mask.size()) == 1:
          assert encoder_out.size(0) == 1 and encoder_out.size(
              1
          ) == encoder_padding_mask.size(0)
      else:
          assert encoder_out.size(0) == encoder_padding_mask.size(
              0
          ) and encoder_out.size(1) == encoder_padding_mask.size(1)
      if cache is None:
          assert bs == encoder_out.size(0)
      else:
          assert bs % encoder_out.size(0) == 0
      output = LSTransformerDecoderFunc.apply(
          decoder_states,
          encoder_out,
          encoder_padding_mask,
          self.para,
          self.config,
          cache_list,
      )
      return output.to(self.para)
  
imports: from itertools import zip_longest
  import math
  from dataclasses import dataclass
  import copy
  import torch
  from torch import nn
  from torch.autograd import Function
  from lightseq.training.ops.pytorch.util import copy_para, state_dict, MODEL_ARCH, check_config, calc_offset
  from lightseq.training.ops.pytorch.layer_base import TransformerDecoderLayerBase
label_desc: Use image node_id 9 for calling the LSTransformerDecoderLayer obj's underlying member method code with example usage: obj.forward(decoder_states, encoder_out, encoder_padding_mask, cache) and returns: output