我有一个用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矩阵的情况下手动进行矩阵乘法,但是内置的*(,)运算符的运行速度比使用+*的运行速度快,至少在我看来尝试,并且这样做似乎比简单地构造Q1有更多的开销。

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

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

旧代码:

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

最佳答案

该代码尝试通过将计算简化为两个嵌套的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.


分配非常少,每个矩阵元素都被访问了两次,但以列顺序(即快速顺序)进行了访问。

07-24 09:44