【问题标题】:Joint Entropy Performance in JuliaJulia 中的联合熵性能
【发布时间】:2015-03-02 00:11:25
【问题描述】:

我写了一个函数来计算矩阵中每一列对的联合熵。但我想提高时间和内存方面的性能。

函数如下所示:

function jointentropy(aln)
  mat = Array(Float64,size(aln,2),size(aln,2))

  for i in combinations(1:size(aln,2),2)
    a = i[1]
    b = i[2]
    mina, maxa = extrema(aln[:,a])
    minb, maxb = extrema(aln[:,b])
    h = Array(Float64,(maxa-mina+1,maxb-minb+1))
    h = hist2d([aln[:,a] aln[:,b]],mina-1:1:maxa,minb-1:1:maxb)[3]
    h = h/size(aln[:,1],1)
    I,J,V = findnz(h)
    l = sparse(I,J,log2(V),maxa-mina+1,maxb-minb+1)
    mat[b,a] = - sum(l.*h)
  end
  return mat
end

进入此函数的矩阵如下所示:

rand(45:122,rand(1:2000),rand(1:2000))

一个 500x500 矩阵的示例导致以下 @time 输出:

elapsed time: 33.692081413 seconds (33938843192 bytes allocated, 36.42% gc time)

...这似乎是一大堆内存...

关于如何加快此功能并减少内存分配的任何建议?

提前感谢您的帮助!

【问题讨论】:

    标签: performance julia entropy


    【解决方案1】:

    这里有一些想法可以加快你的功能。

    • 如果所有列的范围大致相同,您可以将极值计算移到循环外并重用相同的h 数组。

    • hist2d 创建一个新数组:您可以使用hist2d! 重复使用之前的数组。

    • 赋值h = h/size(aln[:,1],1) 创建一个新数组。

    • h = h/size(aln[:,1],1) 中的除法是针对数组的所有元素完成的,包括零。

    • 您可以使用循环代替findnz 和稀疏矩阵(findnz 已经包含循环)。

    .

    function jointentropy2(aln)
      n1 = size(aln,1)
      n2 = size(aln,2)
      mat = Array(Float64,n2,n2) 
    
      lower, upper = extrema(aln)
      m = upper-lower+1
      h = Array(Float64,(m,m))
      for a in 1:n2
        for b in (a+1):n2
          Base.hist2d!(h,[aln[:,a] aln[:,b]],lower-1:1:upper,lower-1:1:upper)[3]
          s = 0
          for i in 1:m
            for j in 1:m
              if h[i,j] != 0
                p = h[i,j]  / n1
                s += p * log2(p)
              end
            end
          end
          mat[b,a] = - s
        end
      end
      return mat
    end
    

    这是初始函数的两倍, 并且内存分配除以 4。

    aln = rand(45:122,500,400)
    
    @time x = jointentropy(aln)
    # elapsed time: 26.946314168 seconds (21697858752 bytes allocated, 29.97% gc time)
    
    @time y = jointentropy2(aln)
    # elapsed time: 13.626282821 seconds (5087119968 bytes allocated, 16.21% gc time)
    
    x - y  # approximately zero (at least below the diagonal -- 
           # the matrix was not initialized above it)
    

    下一个优化对象是hist2d(在这里,您可以使用循环和稀疏矩阵)。

    @profile jointentropy2(aln)
    Profile.print()
    

    【讨论】:

    • 非常感谢!尤其是 hist2d 的重建确实节省了很多时间。对于 500x400 矩阵,即:elapsed time: 1.766426231 seconds (1328912 bytes allocated)。相当可观的速度提升...这甚至比 R 中用 c++ 编写的类似函数快四倍...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2018-06-30
    • 2017-07-23
    • 2016-12-12
    • 2016-12-15
    • 1970-01-01
    • 2012-06-02
    相关资源
    最近更新 更多