为什么计算 1/(n * log(n) - n) 会破坏计算机?

Why does calculating 1/(n * log(n) - n) break the computer?

最近我偶然发现了这个问题Wolfram says sum diverges, but Mathematica gives a numerical value。它说 1/(n * log(n) - n) 不可求和(或者在数学上不收敛是正确的)。有趣的是,我们仍然可以尝试用数字计算总和,尽管它是 'not summable'。 Mathematica 给出 ~ 6.1 作为数字答案。

好的。我认为,让我们尝试在该系列总和的 PHP 脚本中重现该数字(或类似的数字)。我的代码是:

$formula = function ($n) {return 1/($n * log($n) - $n);};
$n=2;
$sum=0;

while(true) {
    $term_n = $formula($n);
    $sum += $term_n;
    if ($n++ % 100000 == 0) {
        if ($sum > 5.8)
            usleep(1000);
        echo "n=".number_format($n-1)."; sum={$sum}; error={$term_n}\n";
    }
}

我的算法一直计算到 5.866 的答案,然后发生了以下两种情况之一:

  1. 要么 Ubuntu 崩溃/冻结
  2. 或者Linux终止了我的计算脚本进程

这是在大约 3400 万次迭代后发生的。

后来我检查了 CPU 负载如何随着计算更多级数项而变化。

现在,有趣的部分: 在大约 2200 万次迭代中,内核显示出在它们之间切换任务的困难:

后来,在大约 3300 万次迭代中,内核达到了无 return 点——它们根本拒绝工作:

问题是 - sum 5.866 有什么特别之处以至于它会导致计算机崩溃? - 考虑到迭代次数 N 都不是很大(只是3400 万),第 N 项也不是很小(只有 1.7E-9)——所以没有理由出现奇点。

只是猜测,但听起来计算机 运行 内存不足。您的脚本没有显式分配任何内存,但也许您的 PHP 版本有错误并且正在以某种方式泄漏内存。

如果可用内存耗尽,那确实会导致 运行 OS 崩溃,或提示它杀死您的脚本以保护自己。

如果系统开始大量使用交换 space 进行补偿,那会暂时停止您的脚本,导致您观察到的 CPU 图表出现波动。

我已将问题缩小到根源 - 脚本中执行的函数调用越多 - 泄漏的 ram 越多。调用哪个函数并不重要——用户定义的、sin()、log() 或 min(,) 或其他任何函数。所以我怀疑这是 PHP 核心中的一个错误,它在某些特定条件下发生/ OS 内核。

测试代码:

define('AMOUNT', 2000000);

if ($argc == 1)
    for ($i=AMOUNT; $i <= 3*AMOUNT; $i+=AMOUNT) 
        shell_exec('php ' . __FILE__ . " {$i}");
else 
    for ($i=0; $i < $argv[1]; $i++)
        sin(1);
    /*
    Change line above into something without a function call to stop memory leak :
    $x++; // for example
    */

生成这样的内存泄漏图: