sig
  type dim3 = { x : int; y : int; z : int; }
  type specificLibrary = Cuda | OpenCL | Both
  type context
  type generalInfo = {
    name : string;
    totalGlobalMem : int;
    localMemSize : int;
    clockRate : int;
    totalConstMem : int;
    multiProcessorCount : int;
    eccEnabled : bool;
    id : int;
    ctx : Devices.context;
  }
  type cudaInfo = {
    major : int;
    minor : int;
    regsPerBlock : int;
    warpSize : int;
    memPitch : int;
    maxThreadsPerBlock : int;
    maxThreadsDim : Devices.dim3;
    maxGridSize : Devices.dim3;
    textureAlignment : int;
    deviceOverlap : bool;
    kernelExecTimeoutEnabled : bool;
    integrated : bool;
    canMapHostMemory : bool;
    computeMode : int;
    concurrentKernels : bool;
    pciBusID : int;
    pciDeviceID : int;
    driverVersion : int;
  }
  type platformInfo = {
    platform_profile : string;
    platform_version : string;
    platform_name : string;
    platform_vendor : string;
    platform_extensions : string;
    num_devices : int;
  }
  type deviceType =
      CL_DEVICE_TYPE_CPU
    | CL_DEVICE_TYPE_GPU
    | CL_DEVICE_TYPE_ACCELERATOR
    | CL_DEVICE_TYPE_DEFAULT
  type clDeviceFPConfig =
      CL_FP_DENORM
    | CL_FP_INF_NAN
    | CL_FP_ROUND_TO_NEAREST
    | CL_FP_ROUND_TO_ZERO
    | CL_FP_ROUND_TO_INF
    | CL_FP_FMA
    | CL_FP_NONE
  type clDeviceQueueProperties =
      CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
    | CL_QUEUE_PROFILING_ENABLE
  type clDeviceGlobalMemCacheType =
      CL_READ_WRITE_CACHE
    | CL_READ_ONLY_CACHE
    | CL_NONE
  type clDeviceLocalMemType = CL_LOCAL | CL_GLOBAL
  type clDeviceExecutionCapabilities = CL_EXEC_KERNEL | CL_EXEC_NATIVE_KERNEL
  type clDeviceID
  type openCLInfo = {
    platform_info : Devices.platformInfo;
    device_type : Devices.deviceType;
    profile : string;
    version : string;
    vendor : string;
    extensions : string;
    vendor_id : int;
    max_work_item_dimensions : int;
    address_bits : int;
    max_mem_alloc_size : int;
    image_support : bool;
    max_read_image_args : int;
    max_write_image_args : int;
    max_samplers : int;
    mem_base_addr_align : int;
    min_data_type_align_size : int;
    global_mem_cacheline_size : int;
    global_mem_cache_size : int;
    max_constant_args : int;
    endian_little : bool;
    available : bool;
    compiler_available : bool;
    single_fp_config : Devices.clDeviceFPConfig;
    global_mem_cache_type : Devices.clDeviceGlobalMemCacheType;
    queue_properties : Devices.clDeviceQueueProperties;
    local_mem_type : Devices.clDeviceLocalMemType;
    double_fp_config : Devices.clDeviceFPConfig;
    max_constant_buffer_size : int;
    execution_capabilities : Devices.clDeviceExecutionCapabilities;
    half_fp_config : Devices.clDeviceFPConfig;
    max_work_group_size : int;
    image2D_max_height : int;
    image2D_max_width : int;
    image3D_max_depth : int;
    image3D_max_height : int;
    image3D_max_width : int;
    max_parameter_size : int;
    max_work_item_size : Devices.dim3;
    prefered_vector_width_char : int;
    prefered_vector_width_short : int;
    prefered_vector_width_int : int;
    prefered_vector_width_long : int;
    prefered_vector_width_float : int;
    prefered_vector_width_double : int;
    profiling_timer_resolution : int;
    driver_version : string;
    device_id : Devices.clDeviceID;
  }
  type specificInfo =
      CudaInfo of Devices.cudaInfo
    | OpenCLInfo of Devices.openCLInfo
  type gcInfo
  type events
  type device = {
    general_info : Devices.generalInfo;
    specific_info : Devices.specificInfo;
    gc_info : Devices.gcInfo;
    events : Devices.events;
  }
  external get_cuda_compatible_devices : unit -> int
    = "spoc_getCudaDevicesCount"
  external get_opencl_compatible_devices : unit -> int
    = "spoc_getOpenCLDevicesCount"
  val init : ?only:Devices.specificLibrary -> unit -> Devices.device array
  val cuda_devices : unit -> int
  val opencl_devices : unit -> int
  val gpgpu_devices : unit -> int
  val flush : Devices.device -> ?queue_id:int -> unit -> unit
  val hasCLExtension : Devices.device -> string -> bool
  val allowDouble : Devices.device -> bool
end