class_docstr: Given arrays *values* and *keys* of equal length
  and a number *nkeys* of keys, returns a tuple `(starts,
  lists)`, as follows: *values* and *keys* are sorted
  by *keys*, and the sorted *values* is returned as
  *lists*. Then for each index *i* in ``range(nkeys)``,
  *starts[i]* is written to indicating where the
  group of *values* belonging to the key with index
  *i* begins. It implicitly ends at *starts[i+1]*.
  
  ``starts`` is built so that it has ``nkeys + 1`` entries, so that
  the *i*'th entry is the start of the *i*'th list, and the
  *i*'th entry is the index one past the *i*'th list's end,
  even for the last list.
  
  This implies that all lists are contiguous.
  
  .. note:: This functionality is provided as a preview. Its
      interface is subject to change until this notice is removed.
  
  .. versionadded:: 2013.1
code: def __init__(self, context):
      self.context = context
  
imports: from dataclasses import dataclass
  from typing import Optional
  import numpy
  import pyopencl
  import pyopencl.array
  from pyopencl.elementwise import ElementwiseKernel
  from pyopencl.scan import ScanTemplate, GenericScanKernel
  from pyopencl.tools import dtype_to_ctype, get_arg_offset_adjuster_code
  from pytools import memoize, memoize_method
  from mako.template import Template
label_desc: Use image node_id 1 to create a new KeyValueSorter object  with example: obj = KeyValueSorter(context)