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