我读了this post并意识到朱莉娅的循环速度更快。因此,我决定将矢量化代码更改为循环。但是,我必须在循环中使用一些if语句,但是在添加了更多if语句后,我的循环速度变慢了。
考虑一下我直接从帖子中复制的摘录:
function devectorized()
a = [1.0, 1.0]
b = [2.0, 2.0]
x = [NaN, NaN]
for i in 1:1000000
for index in 1:2
x[index] = a[index] + b[index]
end
end
return
end
function time(N)
timings = Array(Float64, N)
# Force compilation
devectorized()
for itr in 1:N
timings[itr] = @elapsed devectorized()
end
return timings
end
然后我添加了一些if语句来测试速度:
function devectorized2()
a = [1.0, 1.0]
b = [2.0, 2.0]
x = [NaN, NaN]
for i in 1:1000000
for index in 1:2
####repeat this 6 times
if index * i < 20
x[index] = a[index] - b[index]
else
x[index] = a[index] + b[index]
end
####
end
end
return
end
我重复了六次这个块:
if index * i < 20
x[index] = a[index] - b[index]
else
x[index] = a[index] + b[index]
end
为了简洁起见,我不会在示例代码中重复此块。在重复if语句6次之后,devectorized2()
花了3倍的时间。
我有两个问题:
答案 0 :(得分:2)
首先,我不认为这里的表现很奇怪,因为你在为你的功能添加了很多工作。
其次,你实际上应该return x
,否则编译器可能会决定你没有使用x
,只是跳过整个计算,这会彻底混淆时间。
第三,回答你的问题1:你可以这样实现:
x[index] = a[index] + ifelse(index * i < 20, -1, 1) * b[index]
在某些情况下,这可能会更快,但不一定在您的情况下,分支很容易预测。有时您也可以使用Bool
来获得加速,例如:
x[index] = a[index] + (2*(index * i >= 20)-1) * b[index]
同样,在你的例子中,这没有多大帮助,但有时候这种方法可以给你一个不错的加速。
BTW:循环不再总是优于矢量化代码。您链接的帖子很旧。看一下this blog post,它展示了矢量化代码如何实现与循环代码类似的性能。但是,在许多情况下,循环是实现目标的最清晰,最简单,最快捷的方法。