使用 gp2c 时发生堆栈溢出,但在同一程序中直接使用 gp 时不会发生堆栈溢出 (PARI/GP)

Stack Overflow when using gp2c but not when using gp directly with the same program (PARI/GP)

所以我想使用 gp 从特定的 projecteuler 问题计算总和。这是公认不可读的代码:

{
n = 10000;
m=100;
sum(k=1,n,eulerphi(k),0.) - (sum(k=1,n,eulerphi(k)*(k * binomial(n-k,m-1) + sum(p = max(m + k - n - 1,1), k-1, (k-p)*binomial(n+p-k-1,m-2),0.)), 0.))/binomial(n,m)
}

此代码需要两到三分钟才能在我相当普通的机器上输出答案,但它不会超过默认值 parisize = 8000000(大约 8 MB 内存)。

现在,我在某处读到 gp2cgp 脚本编译成 c 代码可以提高性能。

所以我刚刚制作了一个 program.gp 文件:

calculate() = {n = 10000; m=100; sum(k=1,n,eulerphi(k),0.) - (sum(k=1,n,eulerphi(k)*(k * binomial(n-k,m-1) + sum(p = max(m + k - n - 1,1), k-1, (k-p)*binomial(n+p-k-1,m-2),0.)), 0.))/binomial(n,m)}

和运行它与gp2c-run program.gp

在出现的交互提示中,我刚刚执行了calculate()。然而,令我惊讶的是,即使我将 parisizemax 更改为将近 2 GB,我仍会出现堆栈溢出,要求我增加堆栈大小。

? default(parisizemax, 2000000000)
  ***   Warning: new maximum stack size = 2000003072 (1907.352 Mbytes).
? calculate()
  *** calculate: Warning: increasing stack size to 16000000.
  *** calculate: Warning: increasing stack size to 32000000.
  *** calculate: Warning: increasing stack size to 64000000.
  *** calculate: Warning: increasing stack size to 128000000.
  *** calculate: Warning: increasing stack size to 256000000.
  *** calculate: Warning: increasing stack size to 512000000.
  *** calculate: Warning: increasing stack size to 1024000000.
  *** calculate: Warning: increasing stack size to 2000003072.
  ***   at top-level: calculate()
  ***                 ^-----------
  *** calculate: the PARI stack overflows !
  current stack size: 2000003072 (1907.352 Mbytes)
  [hint] you can increase 'parisizemax' using default()

  ***   Break loop: type 'break' to go back to GP prompt

为什么同一个程序编译成 c 需要那么多额外的内存? 作为参考,n = 1000 而不是 10000 的同一程序仅在将堆栈大小增加到 256000000 (250 MB) 后才显示答案,而仅使用 gp 时它只需要默认的 8 MB。有些东西没有加起来。

默认情况下,gp2cgp2c-run 都不会生成处理 PARI 堆栈的代码,这意味着您会很快出现堆栈溢出。使用 gp2c-run -g program.gp-g 标志将导致 gp2c 在计算过程中清理堆栈。 the gp2c tutorial.

中就有这样的例子