Bash 为什么生成更多的随机数据要慢得多?
我想生成大量的随机数。我编写了下面的bash命令(请注意,我在这里使用Bash 为什么生成更多的随机数据要慢得多?,bash,random,pipe,brace-expansion,Bash,Random,Pipe,Brace Expansion,我想生成大量的随机数。我编写了下面的bash命令(请注意,我在这里使用cat是为了演示;在我的实际用例中,我将数字管道化到一个流程中): 数字以很低的速度打印出来。但是,如果生成的量较小,则速度会快得多: for i in {1..9999}; do echo -e "$(cat /dev/urandom | tr -dc '0-9' | fold -w 5 | head -n 1)"; done | cat 请注意,唯一的区别是9999,而不是9999999 为什么会这样
cat
是为了演示;在我的实际用例中,我将数字管道化到一个流程中):
数字以很低的速度打印出来。但是,如果生成的量较小,则速度会快得多:
for i in {1..9999}; do echo -e "$(cat /dev/urandom | tr -dc '0-9' | fold -w 5 | head -n 1)"; done | cat
请注意,唯一的区别是9999
,而不是9999999
为什么会这样?数据是否缓冲在某个地方?是否有办法对此进行优化,以便将随机数立即输送到cat
为什么会这样
生成{1..9999999}
100000000个参数,然后解析它们需要bash分配大量内存。这严重阻碍了整个系统
此外,从/dev/uradom
读取大量数据,约96%的数据通过tr-dc“0-9”
过滤掉。这大大耗尽了熵池,并进一步阻碍了整个系统
数据是否缓冲在某个地方
每个进程都有自己的缓冲区,因此:
正在缓冲cat/dev/uradom
正在缓冲tr-dc'0-9'
是缓冲折叠-w5
正在缓冲磁头-n1
- 管道的左侧(shell)有自己的缓冲区
- 而右侧-
有自己的缓冲区| cat
头-n1
和管道右侧|cat
的输入缓冲,也就是4个输出缓冲区
还有,拯救动物和动物。使用tr
为什么会这样
生成{1..9999999}
100000000个参数,然后解析它们需要bash分配大量内存。这严重阻碍了整个系统
此外,从/dev/uradom
读取大量数据,约96%的数据通过tr-dc“0-9”
过滤掉。这大大耗尽了熵池,并进一步阻碍了整个系统
数据是否缓冲在某个地方
每个进程都有自己的缓冲区,因此:
cat/dev/uradom
正在缓冲
tr-dc'0-9'
正在缓冲
折叠-w5
是缓冲
磁头-n1
正在缓冲
- 管道的左侧(shell)有自己的缓冲区
- 而右侧-
| cat
有自己的缓冲区
这是6个缓冲区。即使忽略来自头-n1
和管道右侧|cat
的输入缓冲,也就是4个输出缓冲区
还有,拯救动物和动物。使用tr为什么在循环中运行这个?您只需运行一组命令即可生成所有内容,例如:
cat /dev/urandom | tr -dc '0-9' | fold -w 5 | head -n 100000000
即,只生成单个数字流,而不是单独生成
我支持使用另一种语言来完成这项工作的建议,它应该更有效。例如,在Python中,它只是:
来自随机导入范围
对于范围内的(100000000):
打印(兰特范围(100000))
为什么要在循环中运行此操作?您只需运行一组命令即可生成所有内容,例如:
cat /dev/urandom | tr -dc '0-9' | fold -w 5 | head -n 100000000
即,只生成单个数字流,而不是单独生成
我支持使用另一种语言来完成这项工作的建议,它应该更有效。例如,在Python中,它只是:
来自随机导入范围
对于范围内的(100000000):
打印(兰特范围(100000))
@SamMason给出了迄今为止最好的答案,因为他完全取消了循环:
cat/dev/uradom | tr-dc'0-9'| fold-w 5 | head-n 100000000
不过,这仍有很大的改进空间。首先,tr-dc'0-9'
只使用了来自/dev/uradom:-)的大约4%的内容;其次,根据这些随机数最终将如何使用,去除前导零可能会产生一些额外的开销——因此一些数字不会被解释为八进制。让我建议一个更好的选择,使用od
命令:
outputFile=/dev/null # For test. Replace with the real file.
count=100000000
od -An -t u2 -w2 /dev/urandom | head -n $count >$outputFile
使用time
命令进行的qick测试表明,这大约比tr
版本快四倍。实际上没有必要使用“另一种语言”,因为od
和head
都经过了高度优化,而且整个过程都以本机速度运行
注意:上述命令将生成16位整数,范围从0到65535(含0到65535)。如果您需要更大的范围,那么您可以选择32位数字,这将为您提供从0到4294967295的范围:
od -An -t u4 -w4 /dev/urandom | head -n $count >$outputFile
如果需要,最终用户可以通过模除法将其缩小到所需的大小。@SamMason提供了迄今为止最好的解决方案,因为他完全取消了循环:
cat/dev/uradom | tr-dc'0-9'| fold-w 5 | head-n 100000000
不过,这仍有很大的改进空间。首先,tr-dc'0-9'
只使用了来自/dev/uradom:-)的大约4%的内容;其次,根据这些随机数最终将如何使用,去除前导零可能会产生一些额外的开销——因此一些数字不会被解释为八进制。让我建议一个更好的选择,使用od
命令:
outputFile=/dev/null # For test. Replace with the real file.
count=100000000
od -An -t u2 -w2 /dev/urandom | head -n $count >$outputFile
使用time
命令进行的qick测试表明,这大约比tr
版本快四倍。实际上没有必要使用“另一种语言”,因为od
和head
都经过了高度优化,而且整个过程都以本机速度运行
注意:上述命令将生成16位整数,范围从0到65535
od -An -t u4 -w4 /dev/urandom | head -n $count >$outputFile