当我运行以下脚本时:
my @arr = [1..5000000];
for($i=0; $i<5000000; $i++) {
$arr[$i] = $i;
if($i % 1000000 == 0) {
print "$i\n";
}
}
它消耗大约500 MB的内存。用于高级编译语言我希望它大约是5M * 4B = 20MB(每个数字4个字节)。
我想这是因为每个值都是标量,而不是简单的二进制数。是否可以通过将这些值视为数字来减少内存占用量,或者仅以500 MB的速度执行此任务?
答案 0 :(得分:4)
如果您正在处理此类大型数组,则可能需要使用the PDL之类的工具包。
(哦,是的,你是对的:它需要很多内存,因为它是一个Perl标量数组。)
答案 1 :(得分:3)
所有Perl值在内部表示为perl标量,它比简单的int消耗方式更多的内存。即使标量只持有int。即使标量是undef
!
正如其他人所建议的那样,如果你真的想要使用这种大型数组,可能需要考虑PDL。
答案 2 :(得分:3)
你总是可以在Perl中使用C或C ++。这可能会让你在一些艰苦的工作中占用很少的空间。 只是一个使用C的想法!
#!/usr/bin/perl
use Inline C;
use strict;
for(my $i=0; $i<5000000; $i++) {
set_array_index($i,$i);
if($i % 1000000 == 0) {
#print "$i\n";
print get_array_index($i)."\n";
}
}
__END__
__C__
int array[5000000];
void set_array_index(int index,int value) {
array[index]=value;
}
int get_array_index(int index) {
if (array[index]==NULL)
return 0;
return array[index];
}
答案 3 :(得分:2)
完整修改我的答案。看看你的代码中有什么,我看到了一些奇怪的东西。
my @arr = [1..5000000];
在此,您将匿名数组引用分配给$arr[0]
。此数组仅包含一个值:数组引用。隐藏的匿名数组拥有500万个数字。
for($i=0; $i<5000000; $i++) {
$arr[$i] = $i;
if($i % 1000000 == 0) {
print "$i\n";
}
}
在这里,您将为数组填充500万个序列号,覆盖声明中的数组引用。
更短的方法是:
my @arr = (1 .. 5_000_000);
也许这会为你节省一些时间。
答案 4 :(得分:2)
以下是交互式pdl2
会话中的几行,展示了如何操作
这可以使用基本的PDL结构来完成:
pdl> $arr = sequence(long, 5000000) + 1; # create pdl data array (a.k.a. a piddle)
pdl> help vars # see, it is only ~19MB
PDL variables in package main::
Name Type Dimension Flow State Mem
----------------------------------------------------------------
$arr Long D [5000000] P 19.07MB
$Pi Double D [] P 0.01KB
pdl> p which( $arr%1000000 == 0 ) # which returns indexes which are true
[999999 1999999 2999999 3999999 4999999]
请参阅在线PDL book PDL可以用于什么的很好的介绍。 PDL mailing lists是最好的 有关PDL使用和开发的信息来源。反应经常是 快速。
答案 5 :(得分:1)
您可以使用pack创建一个长度恰好为5000000 * 4
个字符的二进制字符串,而不是创建数组:
my $numbers = "";
$numbers .= pack("N", $_) for (1..5000000);
绝对应该占用更少的空间。因此,您可以使用substr
和unpack
来获取值。
答案 6 :(得分:1)
也许你可以使用迭代器而不是如此庞大的整数列表。
迭代器为每个新值支付函数调用的开销,但节省了内存。检查MJD高阶Perl第4章(4.2.1)。
如果我没记错的话,范围运营商不会在最新的perls中建立如此庞大的列表。
答案 7 :(得分:0)
或者,为您隐式处理包,有Tie::Array::PackedC:
use Tie::Array::PackedC;
# make @arr use $arr_storage for storing packed elements, by default using 'l!' pack format
tie my @arr, 'Tie::Array::PackedC', my $arr_storage;
vec也可能是有意义的。