2017-04-30 105 views
1

使用productIterator.jl可以迭代笛卡爾乘積輸入中的所有組合。然而,事實證明它不僅僅是「暴力破解這」慢得多:迭代笛卡爾乘積很慢

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在大笛卡爾網格使用朱莉婭v"0.5.1"

回答

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) 

它不顯著影響這一結果,但一般而言,您應在全局範圍內沒有標杆,因爲它是不是代表你如何運行朱莉婭典型方案。相反,將代碼封裝在函數中。

如果您對這兩者有何不同,您可以查看the differencein implementations。 Base的實現是高度優化的,因爲它被用於許多核心結構(比如理解和生成器)。 Iterators.jl實現速度緩慢的原因很多,包括那些調用copy,使用未特化的Any[]向量以及state[2]中的類型不穩定。

+0

非常感謝,但是在這個特定的例子中,我認爲全球範圍內的時間和類型化的功能之間沒有任何區別......? (或者我錯過了什麼?) – luffe

+0

是的,這只是對未來的謹慎,因爲它會導致混淆的結果,而這些結果通常不適用。 –

1

好你的時間輸出告訴你就像:

64.97 M分配product()通過3.5GB內存咀嚼;而「吃」'867MB只有8.12M。

內存分配緩慢。如果你有更多的分配量和更大的分配量來擔心,那會讓你放慢腳步。

+0

謝謝,我認爲這是暗示內存分配是罪魁禍首,問題是爲什麼一個應該是高效率的迭代器需要這麼多的內存...... :)對不起,如果不清楚。 – luffe

+0

啊,好吧,如果你看看Iterator.jl在第245行到第280行做了什麼...有很多很多複製將涉及到。 – user268396

+0

謝謝,也許我應該問他們在github回購上。 – luffe