迭代笛卡尔积很慢

时间:2017-04-30 15:53:09

标签: julia

使用Iterator.jl中的product可以迭代输入的笛卡尔积中的所有组合。然而,它变得比仅仅强迫它慢得多......":

using Iterators

@time(
for tup in product(-100:100, -100:100, -100:100)
    # do something with silly tup
    maximum(tup)
end
)
# 10.033157 seconds (64.97 M allocations: 3.510 GB, 3.03% gc time)

直接嵌套循环:

@time(
for x in -100:100, y in -100:100, z in -100:100
    # do something silly with x, y, z
    maximum([x y z])
end
)
# 0.420949 seconds (8.12 M allocations: 867.374 MB, 4.31% gc time)

有谁知道为什么? (使用从product返回的迭代器将导致块中的代码更简单,允许在大型笛卡尔网格上使用前pmap。使用Julia v"0.5.1"

2 个答案:

答案 0 :(得分:3)

Iterators.jl中的许多功能现在都内置于版本0.6中的Julia< Base.Iterators模块中。您可以使用using Iterators中的版本代替Base.Iterators而不是

julia> @time(
       for tup in product(-100:100, -100:100, -100:100)
           # do something with silly tup
           maximum(tup)
       end
       )
 18.110503 seconds (64.98 M allocations: 3.510 GiB, 3.32% gc time)

julia> @time(
       for tup in Base.Iterators.product(-100:100, -100:100, -100:100)
           # do something with silly tup
           maximum(tup)
       end
       )
  0.658809 seconds (8.12 M allocations: 247.821 MiB, 5.50% gc time)

它并未对此结果产生重大影响,但总的来说,您不应该在全球范围内进行基准测试,因为它不能代表您在Julia中运行典型程序的方式。将代码包装在函数中,而不是。

如果您对两者的不同之处感到好奇,可以查看the difference in implementations。 Base的实现经过高度优化,因为它在许多核心结构(如理解和生成器)中使用。 Iterators.jl实现速度缓慢的原因有很多,包括那些copy调用,使用非专用Any[]向量以及state[2]中的类型不稳定。

答案 1 :(得分:1)

你的时间输出告诉你多少:

通过3.5GB内存咀嚼product()的64.97M分配;而只有8.12M的分配只吃' 867MB。

内存分配很慢。如果你有更多的分配和一个数量级更大的分配担心,那将会减慢你的速度。