Array.safe 和 unsafe_get/set 有什么区别

What's the difference between Array.safe and unsafe_get/set

我在 OCaml forum. I use a lot of Array.set and Array.get (this is most of my code 1 2) 上寻求一些建议来优化我的代码,有人告诉我我可以使用 Array.unsafe_getArray.unsafe_set 来获得一些时间。

在此上下文中,safeunsafe 函数有什么区别?

Array.getArray.set 检查索引是否在数组的范围内。 例如,

[||].(2) 0

失败

Exception: Invalid_argument "index out of bounds".

不安全版本不执行此测试,因此

(Array.unsafe_get [||] 2) 0

因分段错误而失败。

在热循环中,绑定检查测试可能会减慢循环。

不安全版本不执行边界检查。因此,如果您访问超出数组边界的索引,您可能会遇到分段错误或更糟的情况,安全版本只会抛出异常。

如果您已经显式或隐式检查了边界(例如,在循环条件中检查它们),则只应使用不安全函数1,例如,2

(* here [i] is guaranteed to be in range by the loop condition,
   so we can use the unsafe version to remove double check  *)
let unsafe_init_array xs v =
  for i = 0 to Array.length xs - 1 do
    Array.unsafe_set xs i v
  done

1)附带说明一下,我个人从未发现使用这些函数有任何显着的性能提升。我的猜测是,在现代超标量计算机中,推测执行能够并行加载数据和执行边界检查。所以,最终,他们不值得冒险。不过,在不太复杂的架构上可能会有所不同。和往常一样,YMMV,所以请对此持保留态度。

2) 这个循环的安全版本在我的机器上只慢了 6%,但是更安全也更容易阅读,

let safe_init_array xs v =
  for i = 0 to Array.length xs - 1 do
    xs.(i) <- v
  done