生成0&1和1的随机文件

时间:2016-02-07 08:09:08

标签: linux windows binaryfiles

我想生成一个大小为2MB的随机文件,其中包含Linux / Windows中0和1以及我的一个项目。我在linux中试过这个命令:

$ time dd if=/dev/urandom of=/dev/null bs=1M count=2

但是urandom只从内核中获取随机数据,只是复制到我不需要的文件。关于这个的任何想法?谢谢!

2 个答案:

答案 0 :(得分:1)

Colin的解决方案效率极低,因为一种方法会创建一个庞大的列表,然后从中进行选择(因此,如果您想要更大的文件,它将无法正常工作),而另一种方法只会生成一个字符循环

$ time (python3 -c "import random; print(''.join('{0}'.format(n) for n in 
random.sample([0,1]*16*1024*1024, 2*1024*1024)));" > /dev/null)

real    0m4,034s
user    0m3,856s
sys     0m0,137s

$ time (python3 -c "from __future__ import print_function; import random;
[print(random.randint(0,1), end='') for i in range(0, 2*1024*1024)];" > /dev/null)

real    0m6,461s
user    0m6,435s
sys     0m0,016s

tripleee's solution above快得多

$ time (perl -077 -ne 'print unpack("b*")' < /dev/urandom | head -c2M >/dev/null)

real    0m0,007s
user    0m0,006s
sys     0m0,003s

head -c2M这里是将输出限制为2 MB

从理论上讲,在一个周期中处理8个字节而不是仅仅1个字节应该更快,尽管我不知道如何使用perl提高效率

$ time (</dev/urandom perl -nle 'BEGIN{$/=\8; $,=""} printf("%.64b", unpack("Q"))' |
head -c2M >/dev/null)

real    0m0,027s
user    0m0,019s
sys     0m0,010s

What's the fastest way to generate a 1 GB text file containing random digits?中,有一些答案可以以 GB或每秒数十GB的速度生成带有空格分隔符的 十进制位数。强>。仅生成 binary 值且没有您所需要的空格,应该幅值更快。我已经对其中的一些答案进行了调整,以生成0和1。这是我的Ubuntu 18.04 VM(Core i7-8700,2GB RAM)上的一些基准测试:

$ time (LC_ALL=C tr '\0-\377' '[0*128][1*128]' </dev/urandom | head -c2M >/dev/null)

real    0m0,012s
user    0m0,003s
sys     0m0,012s


$ time (jot -s "" -r -c $((2*1024*1024)) 48 49) >/dev/null

real    0m0,297s
user    0m0,279s
sys     0m0,008s

$ time (shuf -r -n $((2*1024*1024)) -i 0-1 -z | tr -d "\0" >/dev/null)

real    0m0,383s
user    0m0,384s
sys     0m0,000s

实际上,/dev/urandom的速度还不够快,可以用</dev/zero openssl enc -aes-128-ctr -nosalt -pass file:/dev/urandom来替换,AES instruction set可以在CPU上提供更快的随机字节流。这是输出20MB文件的时间(因为上述tr命令的2MB运行时间非常短,这使得time返回的结果千差万别)

$ time (</dev/zero openssl enc -aes-128-ctr -nosalt -pass file:/dev/urandom 2> /dev/null |
LC_ALL=C tr '\0-\377' '[0*128][1*128]' | head -c20M >/dev/null)

real    0m0,023s
user    0m0,016s
sys     0m0,023s

$ time (</dev/zero openssl enc -aes-128-ctr -nosalt -pass file:/dev/urandom 2> /dev/null |
perl -077 -ne 'print unpack("b*")' | head -c20M >/dev/null)

real    0m0,038s
user    0m0,024s
sys     0m0,019s

$ time (</dev/zero openssl enc -aes-128-ctr -nosalt -pass file:/dev/urandom 2> /dev/null |
jot -s "" -r -c $((20*1024*1024)) 48 49 >/dev/null)

real    0m2,820s
user    0m2,820s
sys     0m0,000s

答案 1 :(得分:0)

你需要快速的东西吗?否则你可以试试(对我来说花了〜2mn):

$ time (for i in `seq 1 $((2*1024*1024))`; 
  do echo -n $(($RANDOM%2)); done > random.txt)

您可以通过减少$ RANDOM来加快速度,例如:

$ time (i=$((2*1024*1024)); a=0; while [ $i -gt 0 ]; do if [ $a -lt 2 ]; then 
a=$RANDOM; fi; echo -n "$(($a%2))"; let a=$a/2; let i=$i-1; done > random.txt)

在我的情况下,它快了近4倍。它的作用是提取数字的正确位,直到数字不再为1。因此可能会稍微偏向1。

但是,如果您想要快速解决方案,则应该明显不要使用shell脚本语言。你可以在python中轻松完成(在我的情况下这需要约2秒):

$ time (python -c "import random; print(''.join('{0}'.format(n) for n in 
random.sample([0,1]*16*1024*1024, 2*1024*1024)));" > random.txt)

我在这里随机抽取0和1的大清单。但是,我不确定抽样对随机性质的影响。如果列表与样本相比是巨大的,我认为它应该提供高质量的结果,但是它只有8倍大,所以它可能会产生可衡量的影响。

请注意,随机性并不像看起来那么容易。我在这里提出的解决方案的输出并不都具有相同的属性,并且验证它具有哪些通常是复杂的。您可能希望以“更好”的方式交易业绩。随机性,在这种情况下python中的这个版本可能会更好(在我的情况下约为6秒):

$ time (python -c "from __future__ import print_function; import random;
[print(random.randint(0,1), end='') for i in range(0, 2*1024*1024)];" > random.txt)

这里,random.randint应该提供均匀分布的结果。