perl中的C类数组

前端之家收集整理的这篇文章主要介绍了perl中的C类数组前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我想在内存中创建和操作(4字节)整数的大数组.从大到大,我的意思是数亿.阵列中的每个细胞将充当染色体上位置的计数器.我所需要的只是让它适合内存,并快速(O(1))访问元素.我正在计算的东西不是稀疏特征,所以我不能使用稀疏数组.

我不能用常规的perl列表来做这个,因为perl(至少在我的机器上)每个元素使用64个字节,所以我使用的大多数生物的基因组都太大了.我已经尝试通过sqlite和哈希绑定将数据存储在磁盘上,尽管它们有效,但速度非常慢,特别是在普通驱动器上. (当我在4驱动器raid 0上运行时,它的工作原理相当不错).

我以为我可以使用PDL数组,b / c PDL就像C一样存储它的数组,每个元素只使用4个字节.但是,我发现与perl列表相比,更新速度极其缓慢:

use PDL;
use Benchmark qw/cmpthese/;

my $N = 1_000_000;
my @perl = (0 .. $N - 1);
my $pdl = zeroes $N;

cmpthese(-1,{ 
    perl => sub{
        $perl[int(rand($N))]++;
    },pdl => sub{
        # note that I'm not even incrementing here just setting to 1
        $pdl->set(int(rand($N)),1);
    }
});

返回:

Rate  pdl perl
pdl   481208/s   -- -87%
perl 3640889/s 657%   --

有谁知道如何提高pdl set()的性能,或者知道可以实现这一目标的不同模块?

解决方法

我不知道你将获得什么样的性能,但我建议使用记录为 here的vec函数将字符串拆分为位字段.我已经进行了实验,发现我的Perl会容忍长达500_000_000个字符的字符串.对应于125,000,000个32位值.
my $data = "\0" x 500_000_000;
vec($data,32)++;            # Increment data[0]
vec($data,100_000_000,32)++;  # Increment data[100_000_000]

如果这还不够,可能会在Perl的构建中控制限制.或者,如果您认为可以获得更小的字段 – 例如16位计数 – vec将接受任何2到32的幂的字段宽度.

编辑:我认为字符串大小限制与32位Windows进程上2GB最大私有工作集相关.如果您运行Linux或拥有64位perl,您可能比我幸运.

我已经添加了这样的基准程序

my $vec = "\0" x ($N * 4);

cmpthese(-3,1);
    },vec => sub {
        vec($vec,int(rand($N)),32)++; 
    },});

给出这些结果

Rate  pdl  vec perl
pdl   472429/s   -- -76% -85%
vec  1993101/s 322%   -- -37%
perl 3157570/s 568%  58%   --

所以使用vec的速度是原生阵列的三分之二.据推测这是可以接受的.

猜你在找的Perl相关文章