Julia代码优化:向量计算和求和
我在一个 Julia 项目中,我想oneAttempt在下面的代码中优化我的功能。
下面对我的代码进行简要说明:
- 函数
oneAttmept实现了一定的递归算法,返回终端结果。 - 变量
f是通过我algorithm part在下面的代码中编写的算法更新的变量(我会在这个问题中省略这部分)。 - 函数
oneAttempt将在 for 循环下多次调用(超过 1000 次)。
function oneAttempt()
n = 30
m = 900
x = rand(Normal(), n, n)
A = ones(n, n) * sum(sum(x, dims = 1))
# f would be passed to the algorithm below.
# f0 is the initial value of f
f0 = ones(n, n) + x - (1 / m) * A
f = copy(f0)
o = zeros(n, n)
#=
algorithm part:
while loop in which f would be updated many times under complicated algorithm
=#
return f;
end
# the function `oneAttempt` would be called many times (more than 1000 times) under for loop.
我想有更好的优化方法f0,因为我听说向量计算将是 Julia 编码中的一个普通瓶颈。
有没有更好的编码方式?
任何信息,将不胜感激。
回答
您的示例不是完全独立的,这使得提出改进建议变得更加困难,因为我不知道可以在不改变其功能的情况下更改哪些部分。但总的来说,我会说你的问题是你正在创建很多不必要的数组,你的第一个策略应该是减少它。
例如:
A = ones(n, n) * sum(sum(x, dims = 1))
这会在内部创建一个向量sum,然后将其求和。此外,不需要ones(n, n)更多的分配,没有任何目的。相反,写
A = sum(x)
这对整个数组求和x,不需要数组。(我怀疑您来自 Matlab,其中sum(x)对矩阵的列求和(除非它是 1xN 矩阵,在这种情况下它对行求和!),但即使在 Matlab 中,您也可以编写sum(x, [], 'all')而不是sum(sum(x)).)
这里:
f0 = ones(n, n) + x - (1 / m) * A
您还应该避免不必要的分配。无需创建数组,只需使用广播即可。我会这样写:
f0 = (1 + A/m) .+ x # 1 and A/m are both scalar, so don't dot the plus in the parens.
这里
f = copy(f0)
o = zeros(n, n)
你创建更多的数组,一个副本和zeros. 我不知道它们是干什么用的,但我怀疑你不需要它。如果您添加更多上下文,我可以对其发表评论。
但总的来说,减少不必要的数组,改用广播,以及可能的就地操作。
- TIL about `sum(x, [], 'all'` for MATLAB! (Also great answer IMHO)