OCAMLRUNPARAM 不影响堆栈大小

OCAMLRUNPARAM does not affect stack size

我想更改我的堆栈大小,以允许具有许多非尾递归函数的项目在更大的数据上 运行。为此,我尝试为不同的 xxx 值(在 0 到 10G 范围内)设置 OCAMLRUNPARAM="l=xxx",但它没有任何效果。设置 OCAMLRUNPARAM 是否正确?

如果相关:我感兴趣的项目是使用 OCamlMakefile 构建的,目标 native-code.

这是一个最小的示例,其中仅创建了一个大列表而没有尾递归。为了快速查看OCAMLRUNPARAM的设置是否有效果,我编译了程序stacktest.ml:

let rec create l =
  match l with
| 0 -> []
| _ -> "00"::(create (l-1))

let l = create (int_of_string (Sys.argv.(1)))
let _ = print_endline("List of size " ^ string_of_int (List.length l) ^ " created.")

使用命令

ocamlbuild stacktest.native

并通过以下 bash 脚本 foo.sh:

通过(或多或少)二进制搜索粗略地发现堆栈溢出发生在列表的哪个长度
#!/bin/bash
export OCAMLRUNPARAM="l="
increment=1000000
length=1
while [[ $increment > 0 ]] ; do
    while [[ $(./stacktest.native $length) ]]; do
        length=$(($length+$increment))
    done
    length=$(($length-$increment))
    increment=$(($increment/2))
    length=$(($length+$increment))
done
length=$(($length-$increment))
echo "Largest list without overflow: $length"
echo $OCAMLRUNPARAM

这个脚本的 运行 之间的结果各不相同(中间结果甚至在一个 运行 内也不一致,但我们暂时忽略它),但无论是否我叫

bash foo.sh 1

bash foo.sh 1G

即堆栈大小是否设置为 1 或 2^30 个字。

通过 OCAMLRUNPARAM 更改堆栈限制仅适用于字节码可执行文件,OCaml 解释器 运行。本机程序由操作系统处理并直接在 CPU 上执行。因此,为了更改堆栈限制,您需要使用操作系统提供的工具。

例如,在 Linux 上有 ulimit 命令处理许多进程参数,包括堆栈限制。将以下内容添加到您的脚本中

ulimit -s 

而且您会看到结果正在发生变化。