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

问题描述

所以我想使用 gp 计算一个特定投影仪问题的总和。这是公认的不可读的代码

{
n = 10000;
m=100;
sum(k=1,n,eulerphi(k),0.) - (sum(k=1,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 内存)。

现在,我在某处读到将 gp2c 脚本编译为 gp 代码c 可以提高性能

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

calculate() = {n = 10000; m=100; sum(k=1,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中有这样一个例子。