<commit_before>(*
 * OWL - an OCaml numerical library for scientific computing
 * Copyright (c) 2016-2018 <NAME> <<EMAIL>>
 *)

open Owl_graph

open Owl_opencl_base

open Owl_opencl_utils

open Owl_opencl_generated


(* Functor of initialising an OpenCL engine to execute a computation graph. *)

module Make
  (Device : Owl_types_computation_opencl_device.Sig)
  = struct

  module Graph = Owl_computation_engine.Make_Graph (Device)

  open Graph.Optimiser.Operator.Symbol

  open Graph.Optimiser.Operator.Symbol.Shape.Type.Device


  (* utility functions *)

  let make_typed_kernel_name fun_name =
    match A.number with
    | F32 -> "owl_opencl_float32_" ^ fun_name
    | F64 -> "owl_opencl_float64_" ^ fun_name
    | _   -> failwith "make_typed_kernel_name"


  let make_kernel x program fun_name =
    let x_val = (get_value x).(0) in
    let typed_fun = make_typed_kernel_name fun_name in
    let kernel = Kernel.create program typed_fun in
    x_val.kernel <- [| kernel |];
    kernel


  let allocate_cpu_buffer x =
    if is_assigned x = false then (
      let x_shp = node_shape x in
      let cpu_mem = A.empty x_shp in
      let new_val = Device.make_value [|cpu_mem|] [||] [||] [||] in
      set_value x [| new_val |]
    )


  let allocate_gpu_buffer ctx x =
    let x_val = (get_value x).(0) in
    if Array.length x_val.gpu_mem = 0 then (
      let cpu_mem = value_to_arr x_val in
      let flags = [ cl_MEM_USE_HOST_PTR ] in
      let gpu_mem = Buffer.create_bigarray ~flags ctx (Obj.magic cpu_mem) in
      let new_val = Device.make_value [|cpu_mem|] [|gpu_mem|] [||] [||] in
      set_value x [| new_val |]
    )


  let allocate_cpu_gpu_buffer ctx x =
    allocate_cpu_buffer x;
    allocate_gpu_buffer ctx x


  let allocate_from_parent_0 ctx x = allocate_cpu_gpu_buffer ctx x


  let allocate_from_parent_1 ctx x parent =
    let parent_val = (get_value parent).(0) in
    if refnum parent = 1 && get_reuse parent then (
      set_value x [| Device.refer_value parent_val |];
      set_vnode x [| parent |]
    )
    else
      allocate_cpu_gpu_buffer ctx x


  let allocate_from_parent_2 ctx x parent_0 parent_1 =
    let parent_0_val = (get_value parent_0).(0) in
    let parent_1_val = (get_value parent_1).(0) in
    let shp_0 = A.shape (value_to_arr parent_0_val) in
    let shp_1 = A.shape (value_to_arr parent_1_val) in
    let shp_0, shp_1 = Owl_utils_array.align `Left 1 shp_0 shp_1 in
    let shp_x = Owl_utils_infer_shape.broadcast1 shp_0 shp_1 in

    if shp_0 = shp_x && refnum parent_0 = 1 && get_reuse parent_0 then (
      set_value x [| Device.refer_value parent_0_val |];
      set_vnode x [| parent_0 |]
    )
    else if shp_1 = shp_x && refnum parent_1 = 1 && get_reuse parent_1 then (
      set_value x [| Device.refer_value parent_1_val |];
      set_vnode x [| parent_1 |]
    )
    else
      allocate_cpu_gpu_buffer ctx x


  (* a node is initialised iff the kernel is allocated *)
  let is_initialised x =
    let x_val = get_value x in
    if Array.length x_val = 0 then false
    else Array.length x_val.(0).kernel > 0


  let rec _init_term x param =
    Owl_log.debug "init %s ..." (node_to_str x);

    if is_initialised x = false then
      try
        match (get_operator x) with
        | Noop                                        -> _init_xx x param
        | Var                                         -> _init_00 x param
        | Const                                       -> _init_00 x param
        | Empty shape                                 -> _init_xx x param
        | Zeros shape                                 -> _init_xx x param
        | Ones shape                                  -> _init_xx x param
        | Create shape                                -> _init_xx x param
        | Sequential                                  -> failwith "Sequential"
        | Uniform shape                               -> _init_20 x param "uniform"
        | Gaussian                                    -> failwith "Gaussian"
        | Bernoulli (p, shape)                        -> _init_xx x param
        | Init (shape, f)                             -> failwith "Init"
        | Get i                                       -> _init_xx x param
        | Set i                                       -> failwith "Set"
        | GetSlice slice                              -> _init_xx x param
        | SetSlice slice                              -> failwith "SetSlice"
        | Copy                                        -> _init_xx x param
        | Reset                                       -> failwith "Reset"
        | Reshape shape                               -> _init_xx x param
        | Reverse                                     -> _init_xx x param
        | Tile repeats                                -> _init_xx x param
        | Repeat repeats                              -> _init_xx x param
        | Concatenate axis                            -> _init_xx x param
        | Split (axis, parts)                         -> failwith "Split"
        | Draw (axis, n)                              -> failwith "Draw"
        | Map f                                       -> failwith "Map"
        | Fold (axis, f)                              -> failwith "Fold"
        | Scan (axis, f)                              -> failwith "Scan"
        | OneHot depth                                -> _init_xx x param
        | Abs                                         -> _init_01 x param "abs"
        | Neg                                         -> _init_01 x param "neg"
        | Floor                                       -> _init_01 x param "floor"
        | Ceil                                        -> _init_01 x param "ceil"<commit_msg>opencl: design and develop<commit_after>(*
 * OWL - an OCaml numerical library for scientific computing
 * Copyright (c) 2016-2018 <NAME> <<EMAIL>>
 *)

open Owl_graph

open Owl_opencl_base

open Owl_opencl_utils

open Owl_opencl_generated


(* Functor of initialising an OpenCL engine to execute a computation graph. *)

module Make
  (Device : Owl_types_computation_opencl_device.Sig)
  = struct

  module Graph = Owl_computation_engine.Make_Graph (Device)

  open Graph.Optimiser.Operator.Symbol

  open Graph.Optimiser.Operator.Symbol.Shape.Type.Device


  (* utility functions *)

  let make_typed_kernel_name fun_name =
    match A.number with
    | F32 -> "owl_opencl_float32_" ^ fun_name
    | F64 -> "owl_opencl_float64_" ^ fun_name
    | _   -> failwith "make_typed_kernel_name"


  let make_kernel x program fun_name =
    let x_val = (get_value x).(0) in
    let typed_fun = make_typed_kernel_name fun_name in
    let kernel = Kernel.create program typed_fun in
    x_val.kernel <- [| kernel |];
    kernel


  let allocate_cpu_buffer x =
    if is_assigned x = false then (
      let x_shp = node_shape x in
      let cpu_mem = A.empty x_shp in
      let new_val = Device.make_value [|cpu_mem|] [||] [||] [||] in
      set_value x [| new_val |]
    )


  let allocate_gpu_buffer ctx x =
    let x_val = (get_value x).(0) in
    if Array.length x_val.gpu_mem = 0 then (
      let cpu_mem = value_to_arr x_val in
      let flags = [ cl_MEM_USE_HOST_PTR ] in
      let gpu_mem = Buffer.create_bigarray ~flags ctx (Obj.magic cpu_mem) in
      let new_val = Device.make_value [|cpu_mem|] [|gpu_mem|] [||] [||] in
      set_value x [| new_val |]
    )


  let allocate_cpu_gpu_buffer ctx x =
    allocate_cpu_buffer x;
    allocate_gpu_buffer ctx x


  let allocate_from_parent_0 ctx x = allocate_cpu_gpu_buffer ctx x


  let allocate_from_parent_1 ctx x parent =
    let parent_val = (get_value parent).(0) in
    if refnum parent = 1 && get_reuse parent then (
      set_value x [| Device.refer_value parent_val |];
      set_vnode x [| parent |]
    )
    else
      allocate_cpu_gpu_buffer ctx x


  let allocate_from_parent_2 ctx x parent_0 parent_1 =
    let parent_0_val = (get_value parent_0).(0) in
    let parent_1_val = (get_value parent_1).(0) in
    let shp_0 = A.shape (value_to_arr parent_0_val) in
    let shp_1 = A.shape (value_to_arr parent_1_val) in
    let shp_0, shp_1 = Owl_utils_array.align `Left 1 shp_0 shp_1 in
    let shp_x = Owl_utils_infer_shape.broadcast1 shp_0 shp_1 in

    if shp_0 = shp_x && refnum parent_0 = 1 && get_reuse parent_0 then (
      set_value x [| Device.refer_value parent_0_val |];
      set_vnode x [| parent_0 |]
    )
    else if shp_1 = shp_x && refnum parent_1 = 1 && get_reuse parent_1 then (
      set_value x [| Device.refer_value parent_1_val |];
      set_vnode x [| parent_1 |]
    )
    else
      allocate_cpu_gpu_buffer ctx x


  (* a node is initialised iff the kernel is allocated *)
  let is_initialised x =
    let x_val = get_value x in
    if Array.length x_val = 0 then false
    else Array.length x_val.(0).kernel > 0


  let rec _init_term x param =
    Owl_log.debug "init %s ..." (node_to_str x);

    if is_initialised x = false then
      try
        match (get_operator x) with
        | Noop                                        -> _init_xx x param
        | Var                                         -> _init_00 x param
        | Const                                       -> _init_00 x param
        | Empty shape                                 -> _init_00 x param
        | Zeros shape                                 -> _init_xx x param
        | Ones shape                                  -> _init_xx x param
        | Create shape                                -> _init_xx x param
        | Sequential                                  -> failwith "Sequential"
        | Uniform shape                               -> _init_20 x param "uniform"
        | Gaussian                                    -> failwith "Gaussian"
        | Bernoulli (p, shape)                        -> _init_xx x param
        | Init (shape, f)                             -> failwith "Init"
        | Get i                                       -> _init_xx x param
        | Set i                                       -> failwith "Set"
        | GetSlice slice                              -> _init_xx x param
        | SetSlice slice                              -> failwith "SetSlice"
        | Copy                                        -> _init_xx x param
        | Reset                                       -> failwith "Reset"
        | Reshape shape                               -> _init_xx x param
        | Reverse                                     -> _init_xx x param
        | Tile repeats                                -> _init_xx x param
        | Repeat repeats                              -> _init_xx x param
        | Concatenate axis                            -> _init_xx x param
        | Split (axis, parts)                         -> failwith "Split"
        | Draw (axis, n)                              -> failwith "Draw"
        | Map f                                       -> failwith "Map"
        | Fold (axis, f)                              -> failwith "Fold"
        | Scan (axis, f)                              -> failwith "Scan"
        | OneHot depth                                -> _init_xx x param
        | Abs                                         -> _init_01 x param "abs"
        | Neg                                         -> _init_01 x param "neg"
        | Floor                                       -> _init_01 x param "floor"
        | Ceil                                        -> _init_01 x param "ceil"
{'fraction_non_alphanumeric': 0.0734640522875817, 'fraction_numerical': 0.01289760348583878, 'mean_word_length': 1.3730355665839538, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 82, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '928747', 'n_tokens_mistral': 3485, 'n_tokens_neox': 3317, 'n_words': 954}