code: def _compile_or_get(
      frame, func, args, kernel_getter=None, suffix="__APPLY_UDF"
  ):
      """
      Return a compiled kernel in terms of MaskedTypes that launches a
      kernel equivalent of `f` for the dtypes of `df`. The kernel uses
      a thread for each row and calls `f` using that rows data / mask
      to produce an output value and output validity for each row.
  
      If the UDF has already been compiled for this requested dtypes,
      a cached version will be returned instead of running compilation.
  
      CUDA kernels are void and do not return values. Thus, we need to
      preallocate a column of the correct dtype and pass it in as one of
      the kernel arguments. This creates a chicken-and-egg problem where
      we need the column type to compile the kernel, but normally we would
      be getting that type FROM compiling the kernel (and letting numba
      determine it as a return value). As a workaround, we compile the UDF
      itself outside the final kernel to invoke a full typing pass, which
      unfortunately is difficult to do without running full compilation.
      we then obtain the return type from that separate compilation and
      use it to allocate an output column of the right dtype.
      """
      if not all(is_scalar(arg) for arg in args):
          raise TypeError(
              "only scalar valued args are supported by apply"
          )
  
      # check to see if we already compiled this function
      cache_key = _generate_cache_key(frame, func, args, suffix=suffix)
      if precompiled.get(cache_key) is not None:
          kernel, masked_or_scalar = precompiled[cache_key]
          return kernel, masked_or_scalar
  
      # precompile the user udf to get the right return type.
      # could be a MaskedType or a scalar type.
  
      kernel, scalar_return_type = kernel_getter(frame, func, args)
      np_return_type = (
          numpy_support.as_dtype(scalar_return_type)
          if scalar_return_type.is_internal
          else scalar_return_type.np_dtype
      )
  
      precompiled[cache_key] = (kernel, np_return_type)
  
      return kernel, np_return_type
  
imports: import os
  from typing import Any, Callable, Dict
  import cachetools
  import cupy
  import llvmlite.binding
  import numpy
  from cuda import cudart
  from numba import cuda, typeof
  from numba.core.datamodel import default_manager, models
  from numba.core.errors import TypingError
  from numba.core.extending import register_model
  from numba.np import numpy_support
  from numba.types import CPointer, Poison, Record, Tuple, boolean, int64, void
  import rmm
  from cudf._lib.strings_udf import column_from_udf_string_array, column_to_string_view_array
  from cudf.api.types import is_scalar
  from cudf.core.column.column import as_column
  from cudf.core.dtypes import dtype
  from cudf.core.udf.masked_typing import MaskedType
  from cudf.core.udf.strings_typing import str_view_arg_handler, string_view, udf_string
  from cudf.utils import cudautils
  from cudf.utils._numba import _CUDFNumbaConfig, _get_ptx_file
  from cudf.utils.dtypes import BOOL_TYPES, DATETIME_TYPES, NUMERIC_TYPES, STRING_TYPES, TIMEDELTA_TYPES
  from cudf.utils.nvtx_annotation import _cudf_nvtx_annotate
  from cudf.utils.utils import initfunc
label_desc: Use image node_id 9 for calling a global function with example usage: _compile_or_get(frame, func, args, kernel_getter, suffix) and returns: kernel,  np_return_type, kernel,  masked_or_scalar