code: def conv2d_cudnn(
      cfg,
      data,
      kernel,
      strides,
      padding,
      dilation,
      groups=1,
      layout="NCHW",
      out_dtype="float32",
  ):
      """Compute conv2d using CuDNN library"""
      if layout == "NCHW":
          tensor_format = 0  # CUDNN_TENSOR_NCHW
          N, _, H, W = get_const_tuple(data.shape)
      elif layout == "NHWC":
          tensor_format = 1  # CUDNN_TENSOR_NHWC
          N, H, W, _ = get_const_tuple(data.shape)
      else:
          raise ValueError(f"Unsupported layout {layout} in cudnn")
      CO, CI, KH, KW = get_const_tuple(kernel.shape)
  
      # handle dilation
      stride_h, stride_w = (
          (strides, strides) if isinstance(strides, int) else strides
      )
      dilation_h, dilation_w = (
          (dilation, dilation)
          if isinstance(dilation, int)
          else dilation
      )
      KH_dilated = (KH - 1) * dilation_h + 1
      KW_dilated = (KW - 1) * dilation_h + 1
  
      pt, pl, pb, pr = get_pad_tuple(padding, (KH_dilated, KW_dilated))
      if (pt != pb) or (pl != pr):
          raise ValueError("Cudnn doesn't support asymmetric padding.")
  
      OH = (H + pt + pb - KH) // stride_h + 1
      OW = (W + pl + pr - KW) // stride_w + 1
  
      if isinstance(N, int):
          cfg.add_flop(
              groups
              * 2
              * N
              * OH
              * OW
              * CO
              * CI
              * ((KH - 1) * dilation_h + 1)
              * ((KW - 1) * dilation_w + 1)
          )
  
      if data.dtype == "int8" or kernel.dtype == "int8":
          if layout == "NCHW":
              raise ValueError(
                  "NCHW layout do not support int8 in cudnn"
              )
          dtype = "int32"
      else:
          dtype = data.dtype
  
      cfg.define_knob(
          "algo",
          range(
              cudnn.algo_to_index(
                  "fwd", "CUDNN_CONVOLUTION_FWD_ALGO_COUNT"
              )
          ),
      )
      if cfg.is_fallback:
          if cudnn.exists():
              # Let CUDNN choose the best algo, based on benchmarks run
              # on the local machine.  In the future, this should be
              # based on parameters stored in the Target.
              cfg["algo"] = OtherOptionEntity(-1)
          else:
              cfg["algo"] = OtherOptionEntity(0)
  
      return cudnn.conv_forward(
          data,
          kernel,
          [pt, pl],  # cudnn padding pt, pl on both sides of input
          [stride_h, stride_w],
          [dilation_h, dilation_w],
          conv_mode=1,
          tensor_format=tensor_format,
          algo=cfg["algo"].val,
          conv_dtype=dtype,
          groups=groups,
      )
  
file_path: tvm/python/tvm/topi/cuda/conv2d.py
imports: from tvm import te
  from tvm import autotvm
  from tvm.autotvm.task.space import OtherOptionEntity
  from tvm.contrib import cudnn
  from ..None import nn, generic
  from ..nn.utils import get_pad_tuple
  from ..utils import get_const_tuple, traverse_inline
  from .conv2d_direct import schedule_direct_cuda
label_desc: Use image node_id 3 for calling a global function with example usage: conv2d_cudnn(cfg, data, kernel, strides, padding, dilation, groups, layout, out_dtype) and returns: cudnn