【发布时间】:2021-08-23 16:38:19
【问题描述】:
我正在努力优化我的 Julia 代码并使其运行得更快。
我提取了整个代码的一部分,我希望您评估是否存在一些瓶颈,使流程比优化的流程慢。
代码简要说明:
- 设
array1n x n 数组,用randn随机条目初始化 -
array1将在循环中根据某种算法更新,直到array1的所有条目都大于-0.8 - 如果循环未在 100000 次循环内结束,则循环强制结束。
using Random;
function Test()
n=5
sqn = n^2
foo1 = circshift(collect(1:n)', (0, 1))
foo2 = circshift(collect(1:n)', (0, -1))
foo3 = circshift(collect(1:n), 1)
foo4 = circshift(collect(1:n), -1)
# initialize array1 with random entries
array1 = randn(n,n);
# initialize array2 with zeros
array2 = zeros(n,n);
#println(array1);
loop = 0
while minimum(array1) < -0.8 && loop < 100000
loop += 1
bar = zeros(n, n)
# Use simd?
for i = 1:sqn
bar[i] = max(0, array1[i] - 0.2)
end
array2 += bar
adding = zeros(n, n)
# Use simd?
for i = 1:n
for j = 1:n
adding[i, j] =
(1 / 4) * sum([
bar[i, foo1[j]],
bar[i, foo2[j]],
bar[foo3[i], j],
bar[foo4[i], j],
])
end
end
array1 = array1 - bar + adding
end
# println(array1)
# println(array2)
# println(loop)
end
Test()
我想我可以在某些for statement 中使用@simd 来节省时间。
有没有更好的写法或更好的算法?
如果您有除SIMD 以外的任何有用信息,我很乐意听到。
任何信息将不胜感激。
【问题讨论】:
-
SIMD 指令对
bar[i] = max(0, array1[i] - 0.2)有很大帮助,如果编译器没有已经为您自动矢量化。 (你希望如此;矢量化相对容易)。理想情况下,还将array2 += bar工作折叠到该循环中,使用bar的每个向量作为它的产生。所以 IDK 一个典型的 Julia 编译器是否需要任何帮助来向量化它。如果编译器看到每个元素都写在循环内,adding = zeros(n, n)初始化有望优化掉。 -
sum()部分更难:我不了解 Julia,但我认为这是使用一个数组的元素来索引另一个数组,在这种情况下,您需要“收集”指令( AVX2 / AVX -512,或者我认为是 ARM SVE)将向量的元素用作内存中的单独索引。 (如果不这样做,您可以对bar[foo3[i], j]和bar[foo4[i], j]部分进行矢量化,因为它们都是连续j的连续内存。) -
您应该做的第一件事是避免在循环中分配,尤其是在内部循环中。
sum([bar[i, foo1[j]], ...每次创建一个 4 元素数组,它应该只是bar[i, foo1[j]] + ...。然后在循环外定义一次bar和adding,并就地更新它们:@. bar = max(0, array1 - 0.2)和array2 .+= bar和@. array1 = array1 - bar + adding。你可能还想要@inbounds adding[i, j] = ...,这比原来的速度快 10 倍,对我来说。 -
你也可以写
bar[i, mod1(j+1, n)]之类的东西来避免foo1等。它更简单,似乎更快一点。由于mod不是免费的,您可能会考虑使所有数组略大于所需的数组,以便始终安全地索引bar[i, j+1]。或者在大多数i in 2:n-1, j in 2:n-1(不需要mod)的循环中分别迭代边缘(需要mod)。 -
@ten:如果数组的所有部分都在同一点环绕,则将内部循环分成几部分:循环一个连续的部分,然后在另一部分上执行单独的循环。因此,您在任何循环中都不会有任何条件内容,并且您不需要相同数据的冗余副本,这些副本会花费更多的内存带宽/缓存占用空间。 (顺便说一句,“紧固”的意思是“将两个东西固定在一起”,例如用胶水或螺丝钉。“加速”或“加速”确实意味着“加快速度”。)
标签: arrays algorithm optimization julia simd