我有来自长度为1MIO的数据库的位向量,每个位代表一个整数,用于压缩存储:
the bit string : 10110001 from the database
array 2 3 0 1 needed for further processing当前的解决方案是:
my $bitstring =
$sth->fetchrow_array(); # has 2 bits / snp, need 2 convert to I
my $snp_no = 1000000;
for ( my $i = 0; $i <= $snp_no - 1; $i++ ) {
my $A2 = substr ($bitstring ,$j,2);
$j = $j + 2;
my $vec = Bit::Vector->new_Bin(32, $A2);
@bitArray->[$i] = $vec->to_Dec();
}这确实有效,但太慢了:处理一个这样的向量需要一秒钟,而对于数千个向量,处理过程将需要几个小时。
有没有人知道如何让这一切变得更快?
发布于 2014-03-03 22:07:28
如果您从“打包”的数据开始,请使用以下内容:
my @decode =
map [
($_ >> 6) & 3,
($_ >> 4) & 3,
($_ >> 2) & 3,
($_ >> 0) & 3,
],
0x00..0xFF;
my @nums = map @{ $decode[$_] }, unpack 'C*', $bytes;对我来说,1,000,000字节大约需要1.1秒,也就是每个字节1.1微秒。
一个专门的纯C解决方案需要大约一半的时间。
use Inline C => <<'__EOI__';
void decode(AV* av, SV* sv) {
STRLEN len;
U8* p = (U8*)SvPVbyte(sv, len);
av_fill(av, len*4);
av_clear(av);
while (len--) {
av_push(av, newSViv(*p >> 6 ));
av_push(av, newSViv(*p >> 4 & 3));
av_push(av, newSViv(*p >> 2 & 3));
av_push(av, newSViv(*(p++) & 3));
}
}
__EOI__
decode(\my @nums, $bytes);如果从位的二进制表示开始,请首先使用以下内容:
my $bytes = packed('B*', $bits);(这假设位数可以被8整除。如果不能,则使用0进行左填充,并且不要忘记删除在@decode中创建的额外条目。)
发布于 2014-03-03 21:36:05
这样会更快吗?
#!/usr/bin/env perl
use warnings;
use strict;
my %bin2dec = (
'0' => 0,
'1' => 1,
'00' => 0,
'01' => 1,
'10' => 2,
'11' => 3
);
#warn "$_ => $bin2dec{$_}\n" for sort keys %bin2dec;
my @results;
while (<>)
{
foreach my $bitstring (/([01]+)/g)
{
my @result;
#warn "bitstring is $bitstring\n";
for ( my $i = 0 ; $i < length($bitstring) ; $i += 2 )
{
#warn "value is ", substr( $bitstring, $i, 2 ), "\n";
push( @result, $bin2dec{ substr( $bitstring, $i, 2 ) } );
}
push( @results, \@result );
}
}
foreach my $result (@results)
{
print join( ' ', @$result ), "\n";
}已保存到文件b2dec。输出示例:
$ echo 10010101010010010101001111001011010101w00101010 | b2dec
2 1 1 1 1 0 2 1 1 1 0 3 3 0 2 3 1 1 1
0 2 2 2
$ b2dec b2dec
0
0
1
1
0
0
1
1
2
3
1
0https://stackoverflow.com/questions/22145298
复制相似问题