在Julia中优化连接

时间:2016-11-04 18:38:55

标签: optimization julia

我有一个用Julia编写的非常简单的函数,需要运行数百万次。

代码:

function randfunc()
  #rands could be a global variable if desired
  rands = rand(200,100000)
  for i=1:100000
    #the alphabet can continue (and in Q1 as well)
    # rand(1:100000) generates a random number within the number of columns in rands
    a = rand(1:100000) 
    b = rand(1:100000)
    c = rand(1:100000)
    d = rand(1:100000)
    e = rand(1:100000)
    Q1 = hcat(rands[:,a],rands[:,b],rands[:,c],rands[:,d],rands[:,e])
    Q2 = *(Q1.',Q1)
  end
end

有没有办法加速hcat功能或用更高效的东西替换它?

加速此功能的另一种方法是手动进行矩阵乘法而不构造Q1矩阵,但内置*(,)运算符比使用+和{{1}运行得更快至少在我的尝试中,这样做似乎比简单构建Q1有更多的开销。

使用*会有所帮助,但rands = convert(Array{Float32}, rands)实际上更糟(特别是对于矩阵乘法)。 Float16中的元素不能是严格的整数,列向量的数量在Q1中是任意的。

编辑:这个问题的最初概念是试图从数据中获得一种快速的方法来调用矩阵,这些数据随后将成为矩阵乘法的一部分。我编辑了代码以试图解决任何歧义。

旧代码:

rands

2 个答案:

答案 0 :(得分:5)

此代码尝试通过将计算简化为两个嵌套的for循环来优化函数。基本上,这通过根据输入rands矩阵元素扩展表达式来计算原始矩阵形式所表达的相同表达式。返回值是Q2矩阵的行列式的向量。

function randfunc2(rands)
  a,b,c = 0.0,0.0,0.0
  detvec = Vector{Float64}(size(rands,2)-1)
  @inbounds for i=1:(size(rands,2)-1)
    a,b,c = 0.0,0.0,0.0
    @inbounds for j=1:size(rands,1)
      s = rands[j,i]
      t = s*s
      u = s*rands[j,i+1]
      a += t
      b += s*u
      c += u*u
    end
    detvec[i] = a*c-b*b    # calc determinant using 2x2 det formula
    # Q2 = [a b; b c]
  end
  return detvec
end

要使用此功能,请参阅问题中的示例:

rands = rand(200,100000)
randfunc2(rands)        # this returns the determinant vectors.

分配非常小,每个矩阵元素访问两次但按列顺序(快速顺序)。

答案 1 :(得分:3)

将代码分解成更小的部分+使用视图有助于降低约60%的分配:

function randfunc()
    #rands could be a global variable if desired
    n=100000
    rands = rand(200,n)
    for i=1:n-1
        Q1 = hcat(rands[:,[i]],rands[:,[i]].*rands[:,[i+1]])
        Q2 = *(Q1.',Q1)
    end
end

function Q1(r1,r2)
   hcat(r1,r1.*r2) 
end
function some_mult(Q)
    *(Q',Q)
end
function randfunc2()
    n=100000
    #rands could be a global variable if desired
    rands = rand(200,n)
    for i=1:n-1
        Q2 = some_mult(Q1(
            view(rands,:,[i]),
            view(rands,:,[i+1])))
    end
end
@time randfunc()  #1.883301 seconds (3.20 M allocations: 1.228 GB, 30.84% gc time)
@time randfunc2() #1.656203 seconds (2.90 M allocations: 736.978 MB, 31.27% gc time)