实现矩阵函数最有效的方法?

时间:2017-12-06 03:41:54

标签: arrays performance julia

我已经尝试了一段时间来找出处理包含变量的二维数组(即矩阵)的最有效方式。 我通过连接较小的数组构造一个大矩阵,用变量加权。作为一个简化的例子,这就是我目前所做的。

function myMatrix(x::Float64)
    M = vcat(hcat(x*A, C), hcat(C, 2*x*B))
    return M
end

const A = ones(2,2)  
const B = ones(2,2)
const C = zeros(2,2)
y_values = collect(0:0.01:10)

for y in y_values
    eivals, eivecs = eig(myMatrix(y))
    dosomething(eivals,eivecs) 
end

问题:我有更多(更复杂,非对角线)的矩阵,最终的大小非常大。此时,我将该函数调用了几百次。有没有人建议如何使这个过程在运行时更有效?

提前致谢

2 个答案:

答案 0 :(得分:1)

编辑:根据以下评论,这不回答问题。

你的意思是构建矩阵吗?做意识形态的一种方法是使用块矩阵:

M = [x*A   C
    C    2x*B]

不确定这在运行时是否最有效,抱歉。

答案 1 :(得分:0)

这个解决方案,使用在评论中某处提出的预分配,并没有直接解决我的问题(因为我构造矩阵的方式),但对于读这个的人来说它可能仍然有用。另外,我不保证最初使用的#34;效率最高的声明,因为这似乎在很大程度上取决于你的目的,矩阵的大小等等。 Julia的“性能提示”部分也提到了这种方法。

由于存在一些混淆,请考虑以下示例:

function myMatrix(x::Float64)
    M = vcat(hcat(x*A, C), hcat(D, 2*x*B))
    return M
end

function doSomething(A::Array{Float64,2})
    nothing
end

const ArraySize = 1000
const A = ones(ArraySize,ArraySize)  
const B = ones(ArraySize,ArraySize)
const C = rand(ArraySize,ArraySize)
const D = rand(ArraySize,ArraySize)


for i = 1:1000
    ret = myMatrix( convert(Float64,i) )
    doSomething(ret)
end

这确实只是根据一个参数从初始矩阵构造BlockMatrix(函数)。我认为这种重复构造是多余的,事实上,人们可以通过写:

为矩阵预分配内存
function xinc!(ret::Array{T,2}, x::T) where T
    ret[1:ArraySize, 1:ArraySize] = x*A
    ret[1:ArraySize, ArraySize+1:2*ArraySize] = C
    ret[ArraySize+1:2*ArraySize, 1:ArraySize] = D
    ret[ArraySize+1:2*ArraySize, ArraySize+1:2*ArraySize] = 2*x*B
    nothing
end

function doSomething(A::Array{Float64,2})
    nothing
end

const ArraySize = 1000
const A = ones(ArraySize,ArraySize)  
const B = ones(ArraySize,ArraySize)
const C = rand(ArraySize,ArraySize)
const D = rand(ArraySize,ArraySize)



ret = Array{Float64}(2*ArraySize, 2*ArraySize)
for i = 1:1000
    xinc!(ret, convert(Float64,i))
    doSomething(ret)
end

对我来说,第二个代码在9.866s中执行,而第一个代码占用38.076s。

编辑:回复上一条评论,如果我写

function xinc!(ret::Array{T,2}, x::T) where T
    ret = [x*A  C
            D   2*x*B]
    nothing
end

代码需要16.173秒才能执行。我不知道为什么,但这种分配矩阵的方式要慢得多。