class_docstr: Flash-Attention with Split-K. Supports fused int-4 K/V quantization.
  Quantized path will be taken if input K/V have type int32.
  
  Quantization can be row-wise or group-wise (when cls.NUM_GROUPS > 1) along
  the last dimension of K and V. Currently 1, 2, 4, or 8 groups per row are supported.
  Quantization coefficients (scale and shift) are represented as two
  float16 constants per group, packed into int32. Quantization coefficients of
  all groups are placed at the beginning of the row. So, if unquantized K/V have head
  dimension D, the quantized versions have head dimension D // 8 + NUM_GROUPS
  and dtype int32.
  Pseudocode for dequantizing one row can look like:
  group_size = D // 8
  for i in range(NUM_GROUPS):
      group_start = NUM_GROUPS + i * group_size
      group_quant = K[..., group_start: group_start + group_size]
      scale, shift = unpack_int32_into_float16x2(group_quant[0])
      group_dequant = group_quant[..., 1:] * scale + shift
  ...
class_docstr_tok: ["Flash-Attention","with","Split-K",".","Supports","fused","int-4","K\/V","quantization",".","Quantized","path","will","be","taken","if","input","K\/V","have","type","int32",".","Quantization","can","be","row-wise","or","group-wise","(","when","cls.NUM_GROUPS",">","1",")","along","the","last","dimension","of","K","and","V.","Currently","1",",","2",",","4",",","or","8","groups","per","row","are","supported",".","Quantization","coefficients","(","scale","and","shift",")","are","represented","as","two","float16","constants","per","group",",","packed","into","int32",".","Quantization","coefficients","of","all","groups","are","placed","at","the","beginning","of","the","row",".","So",",","if","unquantized","K\/V","have","head","dimension","D",",","the","quantized","versions","have","head","dimension","D","\/\/","8","+","NUM_GROUPS","and","dtype","int32",".","Pseudocode","for","dequantizing","one","row","can","look","like",":","group_size","=","D","\/\/","8","for","i","in","range","(","NUM_GROUPS",")",":","group_start","=","NUM_GROUPS","+","i","*","group_size","group_quant","=","K","[","...",",","group_start",":","group_start","+","group_size","]","scale",",","shift","=","unpack_int32_into_float16x2","(","group_quant","[","0","]",")","group_dequant","=","group_quant","[","...",",","1",":","]","*","scale","+","shift","..."]
code: def not_supported_reasons(cls, d: Inputs) -> List[str]:
      reasons = super(FwOp, cls).not_supported_reasons(d)
      check_lastdim_alignment_stride1(reasons, "query", d.query, 8)
      if d.key.dtype != torch.int32:
          check_lastdim_alignment_stride1(reasons, "key", d.key, 8)
          check_lastdim_alignment_stride1(reasons, "value", d.value, 8)
      if cls.OPERATOR is None:
          reasons.append("triton is not available")
      if d.device.type == "cuda":
          # Has only been tested on 8.0 / 9.0.
          if torch.cuda.get_device_capability(d.device) < (8, 0):
              reasons.append(
                  "requires GPU with sm80 minimum compute capacity, e.g., A100/H100/L4"
              )
  
      q_len = d.query.shape[1]
      if isinstance(
          d.attn_bias, BlockDiagonalCausalWithOffsetPaddedKeysMask
      ):
          seqinfo = d.attn_bias.q_seqinfo
          if q_len != seqinfo.seqstart_py[-1]:
              reasons.append(
                  f"Expected total {seqinfo.seqstart_py[-1]} queries not {q_len}"
              )
          q_len = seqinfo.min_seqlen
          if q_len != seqinfo.max_seqlen:
              reasons.append(
                  "Variable query len is not supported in the presence of causal mask."
              )
  
      if d.key.ndim in [4, 5] and d.key.shape[-2] != 1:
          if (
              d.key.stride(-2) == 0
              and d.value.stride(-2) == 0
              and q_len > 1
          ):
              reasons.append(
                  "multiquery is only supported with query seqlen=1"
              )
  
      if d.attn_bias is not None and q_len > 1:
          reasons.append(
              "query with seqlen > 1 is not supported in the presence of causal mask"
          )
      return reasons
  
imports: from typing import TYPE_CHECKING, Any, List, Optional, Set, Tuple
  import torch
  from ..common import _has_triton21, register_operator
  from .attn_bias import BlockDiagonalCausalWithOffsetPaddedKeysMask
  from .common import AttentionFwOpBase, Context, Inputs, check_lastdim_alignment_stride1
label_desc: Use image node_id 2 for calling the FwOp obj's underlying member method code with example usage: obj.not_supported_reasons(cls, d) and returns: reasons