code: def _get_reduction_source(
      ctx: cl.Context,
      out_type: str,
      out_type_size: int,
      neutral: str,
      reduce_expr: str,
      map_expr: str,
      parsed_args: List[DtypedArgument],
      name: str = "reduce_kernel",
      preamble: str = "",
      arg_prep: str = "",
      device: Optional[cl.Device] = None,
      max_group_size: Optional[int] = None,
  ) -> Tuple[str, int]:
      if device is not None:
          devices = [device]
      else:
          devices = ctx.devices
  
      # {{{ compute group size
  
      def get_dev_group_size(device: cl.Device) -> int:
          # dirty fix for the RV770 boards
          max_work_group_size = device.max_work_group_size
          if "RV770" in device.name:
              max_work_group_size = 64
  
          # compute lmem limit
          from pytools import div_ceil
  
          lmem_wg_size = div_ceil(max_work_group_size, out_type_size)
          result = min(max_work_group_size, lmem_wg_size)
  
          # round down to power of 2
          from pyopencl.tools import bitlog2
  
          return 2 ** bitlog2(result)
  
      group_size = min(get_dev_group_size(dev) for dev in devices)
  
      if max_group_size is not None:
          group_size = min(max_group_size, group_size)
  
      # }}}
  
      from mako.template import Template
      from pyopencl.characterize import has_double_support
  
      arguments = ", ".join(arg.declarator() for arg in parsed_args)
      if parsed_args:
          arguments += ", "
  
      src = str(
          Template(KERNEL).render(
              out_type=out_type,
              group_size=group_size,
              arguments=arguments,
              neutral=neutral,
              reduce_expr=_process_code_for_macro(reduce_expr),
              map_expr=_process_code_for_macro(map_expr),
              name=name,
              preamble=preamble,
              arg_prep=arg_prep,
              double_support=all(
                  has_double_support(dev) for dev in devices
              ),
          )
      )
  
      return src, group_size
  
imports: from dataclasses import dataclass
  from typing import Any, List, Optional, Tuple, Union
  import numpy
  import pyopencl
  from pyopencl.tools import DtypedArgument, KernelTemplateBase, context_dependent_memoize, dtype_to_ctype, _process_code_for_macro
label_desc: Use image node_id 1 for calling a global function with example usage: _get_reduction_source(ctx, out_type, out_type_size, neutral, reduce_expr, map_expr, parsed_args, name, preamble, arg_prep, device, max_group_size) and returns: src,  group_size, unknown