OCaml Bigarray vs array

Reading time ~2 minutes

A simple benchmark

I was recently wondering if I could speed up the access to the element of a matrix in OCaml, using Bigarrays. As the benchmark below shows, it turns out that no, Bigarray was actually slower than matrix operations.

However, a couple of interesting observations can also be made: inlining manually provided a huge increase of the performance for nested arrays, and Owl is actually the fastest solution available (but not by a lot).

open Owl

let n = 10000


let array_at m i j =
  Array.unsafe_get (Array.unsafe_get m i ) j


let sum_array_no_inline n m =
    let a = ref 0. in
    for i = 0 to (n-1) do
      for j = 0 to (n-1) do
        a := !a +. array_at m i j 
      done;
    done;
    !a

let sum_array n m = 
  let a = ref 0. in
  for i = 0 to (n-1) do
    for j = 0 to (n-1) do
      a := !a +. (Array.unsafe_get (Array.unsafe_get m i ) j )
    done;
  done;
  !a


let sum_big_array n m =
  let a = ref 0. in
  for i = 0 to (n-1) do
    for j = 0 to (n-1) do
      a := !a +. (Bigarray.Array2.unsafe_get m i j);
    done;
  done;
  !a


let sum_owl_array n m =
  let a = ref 0. in
  for i = 0 to (n-1) do
    for j = 0 to (n-1) do
      a := !a +. Mat.get m i j;
    done;
  done;
  !a


let sum_owl_array_lib n m =
  Mat.sum' m


let time f x =
  let start = Unix.gettimeofday () in 
  let res = f x in 
  let stop = Unix.gettimeofday () in 
  Printf.printf "Execution time: %fs\n%!" (stop -. start);
  res


let () =
  let arr = Array.init n (fun i -> Array.init n (fun j -> (Random.float 1.0))) in
  
  print_string "[ArrayNoInline] ";
  let a1 = time (sum_array_no_inline n) arr in

  print_string "[Array] ";
  let a2 = time (sum_array n) arr in

  let big_arr = Bigarray.Array2.of_array Bigarray.float32 Bigarray.c_layout arr in
  print_string "[BigArray] ";
  let b = time (sum_big_array n) big_arr in

  let owl_arr = Mat.of_arrays arr in
  print_string "[OwlArray] ";
  let c = time (sum_owl_array n) owl_arr in
  print_string "[OwlArrayLib] ";
  let d = time (sum_owl_array_lib n) owl_arr in

  print_string "\n";
  print_float a1;
 
  print_string "\n";
  print_float a2;
 
  print_string "\n";
  print_float b;

  print_string "\n";
  print_float c;

  print_string "\n";
  print_float d;
  ()

And the results

[ArrayNoInline] Execution time: 0.432230s
[Array] Execution time: 0.105445s
[BigArray] Execution time: 3.037937s
[OwlArray] Execution time: 2.177349s
[OwlArrayLib] Execution time: 0.080217s

Python fast screenshots and locateOnScreen

_Taking screenshots with Python is easy, however, the performance often seems to be an issue, depending on the packages you started with ...… Continue reading