我自己实现了HyperLogLog algorithm
。它工作得很好,但有时我必须获取很多(大约10k-100k)的HLL结构并合并它们。
我将它们作为位字符串存储,所以首先我必须将每个位字符串转换为存储桶。由于HLL很多,所以它需要的时间比我想要的要长。
目前大约80%的运行时为每个HLL调用一行代码:
my @buckets = map { oct '0b'.$_ } unpack('(a5)1024', $bitstring);
有没有办法更快地完成?
如果我们留下HyperLogLog的定义,可以这样解释任务:假设$bitstring
由1024个5位计数器组成(因此每个计数器的值最多可达32)我们必须将其转换为数组1024个整数。
答案 0 :(得分:6)
a
表示任意零填充二进制数据。在这里,您将该数据视为ASCII文本,但它只能包含1
和0
!这是低效的,因为a5
最终使用五个字节。最简单,最有效的解决方案是为每个计数器存储一个8位数字,然后:my @buckets = unpack 'C1024', $bitstring
。
如果你只想在每个计数器上存储5位,那么你最终会节省很少的内存而非常麻烦。你必须使用像这样疯狂的东西来进行往返转换:
my $bitstring = pack "(b5)1024", map { sprintf "%b", $_ } @buckets;
@buckets = map { oct "0b$_" } unpack "(b5)1024", $bitstring;