为什么计算 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
的答案,然后发生了以下两种情况之一:
- 要么 Ubuntu 崩溃/冻结
- 或者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
*/
生成这样的内存泄漏图:
最近我偶然发现了这个问题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
的答案,然后发生了以下两种情况之一:
- 要么 Ubuntu 崩溃/冻结
- 或者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
*/
生成这样的内存泄漏图: