我非常了解Julia关于矢量化等的哲学,我可以接受让我的代码运行速度甚至比Numpy慢十倍,但是为什么这些代码运行比Numpy慢很多?也许代码中有错误;我无法想象这个问题与使用矢量化而不是循环有关。
我正在使用矢量化,因为我的要求不强;此外,内存分配似乎并不那么令人难以置信(并且Numpy证明它非常快)。代码也很容易阅读。
以下代码是用Python编写的;它计算复平面的一部分上的广义连续分数。连续分数由两个不同的函数定义;我使用此代码在此博客上绘制图片:https://kettenreihen.wordpress.com/
Python代码如下;它在大约2秒内计算640x640值:
def K(a, b, C):
s = C.shape
P1 = np.ones(s, dtype=np.complex)
P2 = np.zeros(s, dtype=np.complex)
Q1 = np.zeros(s, dtype=np.complex)
Q2 = np.ones(s, dtype=np.complex)
for n in range(1, 65):
A, B = a(C, n), b(C, n)
P = A*P2 + B*P1
Q = A*Q2 + B*Q1
P1, P2 = P2, P
Q1, Q2 = Q2, Q
return P2/Q2
以下Julia代码也应该这样做,但计算同样的事情需要2到3分钟。
function K(a, b, C)
s = size(C)
P1 = ones(Complex, s)
P2 = zeros(Complex, s)
Q1 = zeros(Complex, s)
Q2 = ones(Complex, s)
for n = 1:64
println(n)
A, B = a(C, n), b(C, n)
P = A.*P2 + B.*P1
Q = A.*Q2 + B.*Q1
P1, P2 = P2, P
Q1, Q2 = Q2, Q
end
return P2./Q2
end
答案 0 :(得分:11)
您正在使用抽象元素类型分配矩阵:Complex
类型是所有特定Complex{T}
类型的抽象超类型。你想要的是一些具体元素类型的数组,如Complex128 == Complex{Float64}
或Complex64 == Complex{Float32}
。据推测,在NumPy dtype=np.complex
中指的是特定的复杂类型,可能相当于Complex128
。
如果你想编写通用的代码并且适用于不同类型的C
矩阵,那么假设C
是一个复杂的矩阵,你想要的是创建1和0的矩阵。相同的元素类型和形状,您只需调用ones
上的zeros
和C
函数即可获得具有正确元素类型和形状的矩阵:
function K(a, b, C)
P1 = ones(C)
P2 = zeros(C)
Q1 = zeros(C)
Q2 = ones(C)
for n = 1:64
println(n)
A, B = a(C, n), b(C, n)
P = A.*P2 + B.*P1
Q = A.*Q2 + B.*Q1
P1, P2 = P2, P
Q1, Q2 = Q2, Q
end
return P2./Q2
end
希望这有助于提高性能。通过预先分配三个矩阵并在矩阵中旋转来执行操作,您可以获得更高的性能。然而,方便的语法支持还没有使它成为一个稳定版本,所以在Julia 0.5上它仍然有点冗长,但可以让你比矢量化版本提升性能。