2016-05-02 144 views
2

我想實現以下循環並行初始化字典。Julia有沒有像SharedDict的東西?

heavy=Dict() 
for item in list 
    heavy[item[1]]=10000000 
end 

其中list是列表的列表,每個項目有三個元素。

我是想這樣的事情:

heavy=Dict() 
@parallel for item in list 
    heavy[item[1]]=10000000 
end 

但是它沒有工作。閱讀documentation我發現了一些可以解決問題的SharedArrays。然而,不清楚如何做同樣的事情,但使用其他數據結構,如Dict()或Set()。先謝謝你。

+0

你是什麼意思,它沒有工作?使用第一個插槽中的1,2和3列表,我得到了一個字典映射1,2和3到10000000. –

+0

我得到一個空的字典。 Heavy:Dict {Any,Any}() –

+0

你是對的,我在運行Julia時沒有任何工作進程。我現在看到了同樣的事情。 –

回答

1

它看起來不像共享字典存在。雖然Dict基於一對Array s,其中一個用於鍵和一個用於值,但它依賴於能夠在插入新項目時調整它們的大小。在工作進程中調整SharedArray似乎做了奇怪的事情,所以你不能把它們交換出去。

如果您可以避開增加內存,您可以創建一對正確長度的鍵/值SharedArray,在並行循環中初始化它們,然後將數據複製到主進程中的Dict。這樣你就可以並行運行任何產生你的值的東西。

不幸的是,如果您的數據不是位類型,那麼SharedArray仍然會有問題。您可以使用DistributedArrays包中的DArray

+2

另一個主要問題是,取決於值的散列方式(Julia中的某些類型通過使用它們的地址進行散列,在不同的進程中可能不相同)。在Julia中擁有共享的關聯數據結構將非常有用。 –

3

下面的方法使用減少@parallel,以達到相同的結果:

list = [[rand(1:3),4,5] for i=1:10000000]; # define random test `list` 

@everywhere rdc(d::Vector,i::Vector) = rdc(rdc(Dict(),d),i) 
@everywhere rdc(d::Dict,i::Vector) = begin d[i[1]] = 1000; d end 
@everywhere rdc(d::Dict,i::Dict) = merge!(d,i) 

heavy = @parallel (rdc) for item in list 
    item 
end 

heavy現在將舉行:

Dict{Any,Any} with 3 entries: 
    2 => 1000 
    3 => 1000 
    1 => 1000 

的想法是產生一個不同的字典每個工人,填充它並最終將字典合併爲一個。希望結合字典的執行速度足以讓這個值得 - 這似乎是合理的。

爲了實現這個想法,我們定義了rdc並使用多次調度使它有三個目的:1)在每個工人上初始化一個新的Dict。 2)將新項目推送到工作人員現有的Dict上。 3)在@parallel的最後階段結合來自不同工作人員的字典。上面代碼中的三種方法(按其各自的順序)執行此操作。

避免了對SharedDict或SharedArray的需求,因爲工作人員在不同的對象上工作,並且在@parallel實現中隱藏了最終的內部工作者通信。