Binary 在Julia中进行频率计数的最佳方法

Binary 在Julia中进行频率计数的最佳方法,binary,statistics,julia,counter,Binary,Statistics,Julia,Counter,我在朱莉娅做频率统计 using PyPlot import StatsBase const stb=StatsBase function getall(fname) b=Mmap.mmap(fname,Vector{Int32}) #a=open(fname) #b=reinterpret(Int32,readbytes(a)) d=stb.countmap(b) x=collect(keys(d)) & 0x7ffffff y=col

我在朱莉娅做频率统计

using PyPlot
import StatsBase
const stb=StatsBase

function getall(fname)
    b=Mmap.mmap(fname,Vector{Int32})
    #a=open(fname)
    #b=reinterpret(Int32,readbytes(a))
    d=stb.countmap(b)
    x=collect(keys(d)) & 0x7ffffff
    y=collect(values(d))
    #plot(x,y,"r^")
    #xlim(0,3000)
    #ylim(0,3e5)
    #grid("on")
    return x,y
end

在python中,我使用
numpy.unique
numpy.memmap
并获得类似的性能(550ms)。朱莉娅的代码能更快吗?有没有其他方法来计数而不是使用StatBases

countmap操作是任何编程语言中的标准操作。此外,它也是“原始”的,就像排序一样,这意味着它必须对输入数据执行基本的常用操作。这类操作很难优化,因为它们在大多数语言中都是类似的操作——如果它们在源语言中速度不够快,则会调用一个专门的例程(read C/Cpp write)

朱莉娅也不例外。一些“原始”线性代数外包给高度优化的库

为了给这个答案提供一个有成效的(而且是积极的)解释,有一些算法方法来处理输入的特殊情况,这将产生比一般算法更快的速度(即使用基于哈希的计数器Dict)。在Julia中编写这些特殊情况的能力代表了它的速度和解决所谓的2语言问题的尝试

具体地说,下面尝试通过传递基于一般哈希的Dict并使用更快的简单哈希和16位查找表来优化32位单词分布不均匀的文件(例如文本文件)

在我的测试文件中,与OP中的
countmap
实现相比,它实现了10%的加速

使用数据结构
函数getall4(fname)
b=Mmap.Mmap(fname,向量{UInt32})
c=零(整数,2^16)
v=数组(UInt16,2^16)
l=长度(b)
对于i=1:l
d1=b[i]&0xFFFF
d2=d1$(b[i]>>16)
如果d1==v[d2+1]
c[d2+1]+=1
其他的
c[d2+1]-=1
结束
如果(c[d2+1]>16)
如果v[d2+1]==d1
c[d2+1]+=1
结束
结束
对于i=1:l
d1=b[i]&0xFFFF
d2=d1$(b[i]>>16)
如果!(v[d2+1]==d1)
推(cc,b[(i+1)>>1])
结束
结束
x=UInt32[]
y=Int[]

对于i=1:(1BTW在post-
getall4
中对二进制文件的测试得到了~3.5倍的改进!将
@inbounds
@simd
添加到
getall4
中的
for
循环的
中,使其比问题中的
getall
的性能提高了约5倍(在我的计算机上为670ms到130ms)这个问题是几年前提出的。在这期间有没有更好的解决方案?
using DataStructures
function getall4(fname)
    b=Mmap.mmap(fname,Vector{UInt32})
    c = zeros(Int,2^16)
    v = Array(UInt16,2^16)
    l = length(b)
    for i=1:l
        d1 = b[i]&0xFFFF
        d2 = d1 $ (b[i]>>16)
        if d1==v[d2+1]
            c[d2+1] += 1
        else
            c[d2+1] -= 1
        end
        if (c[d2+1]<=0)
            c[d2+1] = 1
            v[d2+1] = d1
        end
    end
    cc = DataStructures.counter(UInt32)
    fill!(c,0)
    for i=1:l
        d1 = b[i]&0xFFFF
        d2 = d1 $ (b[i]>>16)
        if v[d2+1]==d1
            c[d2+1] += 1
        end
    end
    for i=1:l
        d1 = b[i]&0xFFFF
        d2 = d1 $ (b[i]>>16)
        if !(v[d2+1]==d1)
            push!(cc,b[(i+1)>>1])
        end
    end
    x = UInt32[]
    y = Int[]
    for i=1:(1<<16)
        if c[i]>0
            push!(x,(UInt32(i)<<16)+v[i])
            push!(y,c[i])
        end
    end
    append!(x,collect(keys(cc.map)))
    append!(y,collect(values(cc.map)))
    x,y
end