code: def __init__(self, device: str = ""):
      if CLDevice.device_ids is None:
          num_platforms = init_c_var(
              ctypes.c_uint32(),
              lambda x: check(
                  cl.clGetPlatformIDs(0, None, ctypes.byref(x))
              ),
          )
          platform_ids = init_c_var(
              (cl.cl_platform_id * num_platforms.value)(),
              lambda x: check(
                  cl.clGetPlatformIDs(num_platforms.value, x, None)
              ),
          )
          for device_type in [
              cl.CL_DEVICE_TYPE_GPU,
              cl.CL_DEVICE_TYPE_DEFAULT,
          ]:
              num_devices = ctypes.c_uint32()
              err = cl.clGetDeviceIDs(
                  platform_ids[0],
                  device_type,
                  0,
                  None,
                  ctypes.byref(num_devices),
              )
              if err == 0 and num_devices.value != 0:
                  break
          if DEBUG >= 1:
              print(
                  f"CLDevice: got {num_platforms.value} platforms and {num_devices.value} devices"
              )
          CLDevice.device_ids = init_c_var(
              (cl.cl_device_id * num_devices.value)(),
              lambda x: check(
                  cl.clGetDeviceIDs(
                      platform_ids[0], device_type, num_devices, x, None
                  )
              ),
          )  # noqa: E501
  
      self.device_id = CLDevice.device_ids[
          0 if ":" not in device else int(device.split(":")[1])
      ]
      self.device_name = (
          cl.clGetDeviceInfo(
              self.device_id,
              cl.CL_DEVICE_NAME,
              256,
              ctypes.byref(buf := ctypes.create_string_buffer(256)),
              ctypes.byref(total := ctypes.c_size_t()),
          ),
          ctypes.string_at(buf, size=total.value).decode(),
      )[
          1
      ]  # noqa: E501
      self.driver_version = (
          cl.clGetDeviceInfo(
              self.device_id,
              cl.CL_DRIVER_VERSION,
              256,
              ctypes.byref(buf := ctypes.create_string_buffer(256)),
              ctypes.byref(total := ctypes.c_size_t()),
          ),
          ctypes.string_at(buf, size=total.value).decode(),
      )[
          1
      ]  # noqa: E501
      self.context = checked(
          cl.clCreateContext(
              None,
              1,
              ctypes.byref(self.device_id),
              cl.clCreateContext.argtypes[3](),
              None,
              ctypes.byref(status := ctypes.c_int32()),
          ),
          status,
      )  # noqa: E501
      self.queue = checked(
          cl.clCreateCommandQueue(
              self.context,
              self.device_id,
              cl.CL_QUEUE_PROFILING_ENABLE,
              ctypes.byref(status),
          ),
          status,
      )
      self.pending_copyin: List[memoryview] = []
  
      compile_key = hashlib.md5(
          self.device_name.encode() + self.driver_version.encode()
      ).hexdigest()
      super().__init__(
          CLAllocator(self),
          LinearizerOptions("GPU"),
          OpenCLRenderer,
          functools.partial(compile_cl, self),
          f"compile_cl_{compile_key}",
          functools.partial(CLProgram, self),
      )
  
imports: from __future__ import annotations
  from typing import Tuple, Optional, List
  import ctypes, functools, hashlib
  import gpuctypes.opencl
  from tinygrad.helpers import init_c_var, to_char_p_p, from_mv, OSX, DEBUG
  from tinygrad.dtype import ImageDType
  from tinygrad.codegen.kernel import LinearizerOptions
  from tinygrad.renderer.cstyle import OpenCLRenderer
  from tinygrad.device import Compiled, LRUAllocator
label_desc: Use image node_id 1 to create a new CLDevice object from inherited base classes: Compiled with example: obj = CLDevice(device)