Bash shell脚本内存不足
我编写了以下随机数生成器外壳脚本:Bash shell脚本内存不足,bash,shell,unix,out-of-memory,Bash,Shell,Unix,Out Of Memory,我编写了以下随机数生成器外壳脚本: for i in $(seq 1 $1) #for as many times, as the first argument ($1) defines... do echo "$i $((RANDOM%$2))" #print the current iteration number and a random number in [0, $2) done 我是这样运行的: ./generator.sh 1000000000 101 > data.tx
for i in $(seq 1 $1) #for as many times, as the first argument ($1) defines...
do
echo "$i $((RANDOM%$2))" #print the current iteration number and a random number in [0, $2)
done
我是这样运行的:
./generator.sh 1000000000 101 > data.txt
在[0100]中生成1B行id和随机数,并将此数据存储在文件data.txt
中
我期望的输出是:
1 39
2 95
3 61
4 27
5 85
6 44
7 49
8 75
9 52
10 66
...
它适用于少量行,但对于1B,我得到以下错误:
./generator.sh:xrealloc:../bash/subst.c:5179:无法分配18446744071562067968字节(已分配4299137024字节)
我的程序的哪个部分产生了错误?
如何逐行写入data.txt
文件?
我已尝试将echo
行替换为:
echo "$i $((RANDOM%$2))" >> $3
其中$3是data.txt
,但我看不出有什么区别。$(seq 1$1)
在迭代之前计算整个列表。因此,存储整个10^9
数字列表需要内存,这非常多
我不确定您是否可以让seq
懒洋洋地运行,即仅在需要时获取下一个数字。您可以改为执行简单的for循环:
for ((i=0; i<$1;++i))
do
echo "$i $((RANDOM%$2))"
done
for((i=0;i问题在于您的for
循环:
for i in $(seq 1 $1)
这将首先展开$(seq 1$1)
,创建一个非常大的列表,然后将其传递到以获取
然而,使用while
,我们可以逐行读取seq
的输出,这将占用少量内存:
seq 1 1000000000 | while read i; do
echo $i
done
如果你想快点,这应该行得通
您将需要使用以下格式使用g++对其进行编译
g++ -o <executable> <C++file>
CTest.cpp
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <sstream>
int main (int argc,char *argv[])
{
std::stringstream ss;
int x = atoi(argv[1]);
for(int i=1;i<=x;i++)
{
ss << i << "\n";
if(i%10000==0)
{
std::cout << ss.rdbuf();
ss.clear();
ss.str(std::string());
}
}
std::cout << ss.rdbuf();
ss.clear();
ss.str(std::string());
}
吸烟者
哈里桑卡
正如您从结果中看到的,我的方法稍微快了60-70*
编辑
因为python很棒
$ cat Py.sh
#!/usr/bin/python
for x in xrange(1, 1000000):
print (x)
"
4比C++慢,如果文件需要一个小时,则这两条线需要4。
编辑2
决定在1000000000行文件
上尝试Python和C++
对于非CPU密集型任务,这似乎使用了大量CPU
PID USER %CPU TIME+ COMMAND
56056 me 96 2:51.43 Py.sh
Python的结果
real 9m37.133s
user 8m53.550s
sys 0m8.348s
c的结果++
real 3m9.047s
user 2m53.400s
sys 0m2.842s
seq 100000000
意味着10e9,这是很多。我做了一个seq 100000000>文件,在我停止它之前,它已经是5G了。@fedorqui我知道,但那是我需要的。我想要大数据用于我的实验,以证明我算法的可伸缩性。我对文件大小没有问题,只是想知道我能做些什么来避免错误r、 @fedorqui我在读了Hari Shankar的回答后明白了你的意思。也谢谢你!事实上我不知道Hari说了什么,所以所有的荣誉都归他:)可能是因为bash首先计算$(…)
&将其保存在内存中。评估完成后,它将为…
部分的实际命令形成命令行。但在第一步完成之前,它收到OOM错误。“不确定是否可以使seq延迟运行”:这是一个shell脚本,你当然可以!你可以将输出通过管道传送到while
,它将逐行读取(见我的答案)。很好!事实上,你可以通过在读取时说来避免管道。i;do…done<@fedorqui谢谢;这更快,但也更难看,IMHO:-)除非有好的方法,否则我会选择可读性(性能)不这样做的理由(通常一个管道在性能方面并不重要,尽管也有例外!)。嗯,something | while
有一个陷阱:如果你想在while
循环中更改变量,它们就不会更改。这是因为原始shell中的变量被复制到新shell中,但更改不会影响原始shell。请参阅这篇好文章:@vefthym It't not“better”;对于同一个问题,这只是一个不同的解决方案。我认为这将有助于您理解这一失败的原因,以及一般的脚本编写。Hari的答案只适用于数字,可能最适合这个特定问题,但我还没有测试过它。如果您关心这一点,它也是特定于bash的不可移植语法……这个解决方案ion还可以处理其他输入,比如一行文本;它还可以移植(顺便说一句,fedorqui的建议不是这样的)@vefthym瓶颈是为每一个number@Carpetsmoker可能是的。如果你把它存储在一个数组中,每n个数字回显一次,而不是每n个数字回显一次,那么在bash中可能也可以很快地完成。我不理解你的评论这不是CPU密集型的
,而其他答案显然是@ CalpPu烟机你失去了我,为什么这是相关的?我不知道你想做什么?也可以在大多数*NIX上默认使用G++,而Python不是。它是相关的,因为一个等效的Python脚本正好是2条容易的行,而不是24条不那么容易的行;它运行的速度几乎一样快,因为C++代码不是CPU密集型的。(因此,性能效益很小)很多系统都是在没有安装C++编译器的情况下安装的,我希望安装Python的系统要多很多。@ CabpEnter在Python中写一个答案?我还是不明白这个问题。没有问题。只是一个注释,对C++和其他程序几乎没有什么性能上的好处。安明语言,为了未来读者的利益。
$ cat Hari.sh
#!/bin/bash
for ((i=0; i<$1;++i))
do
echo "$i $((RANDOM%$2))"
done
$ time ./Hari.sh 1000000 > file
real 0m9.729s
user 0m8.084s
sys 0m1.064s
$ cat Py.sh
#!/usr/bin/python
for x in xrange(1, 1000000):
print (x)
$ time ./Py.sh >file
real 0m0.543s
user 0m0.499s
sys 0m0.016s
PID USER %CPU TIME+ COMMAND
56056 me 96 2:51.43 Py.sh
real 9m37.133s
user 8m53.550s
sys 0m8.348s
real 3m9.047s
user 2m53.400s
sys 0m2.842s