2014-04-25 25 views
4

好的,後續的thisthis的問題。我想修改的代碼是當然的:我可以利用並行化來使這段代碼更快嗎?

function fdtd1d_local(steps, ie = 200) 
    ez = zeros(ie + 1); 
    hy = zeros(ie); 
    for n in 1:steps 
     for i in 2:ie 
      ez[i]+= (hy[i] - hy[i-1]) 
     end 
     ez[1]= sin(n/10) 
     for i in 1:ie 
      hy[i]+= (ez[i+1]- ez[i]) 
     end 
    end 
    (ez, hy) 
end 

fdtd1d_local(1); 
@time sol1=fdtd1d_local(10); 
elapsed time: 3.4292e-5 seconds (4148 bytes allocated) 

而且我天真地試着:

function fdtd1d_local_parallel(steps, ie = 200) 
    ez = dzeros(ie + 1); 
    hy = dzeros(ie); 
    for n in 1:steps 
     for i in 2:ie 
      localpart(ez)[i]+= (hy[i] - hy[i-1]) 
     end 
     localpart(ez)[1]= sin(n/10) 
     for i in 1:ie 
      localpart(hy)[i]+= (ez[i+1]- ez[i]) 
     end 
    end 
    (ez, hy) 
end 

fdtd1d_local_parallel(1); 
@time sol2=fdtd1d_local_parallel(10); 
elapsed time: 0.0418593 seconds (3457828 bytes allocated) 
sol2==sol1 
true 

結果是正確的,但性能更差。所以爲什麼?因爲並行化不適用於雙核舊筆記本電腦,或者我又錯了?

那麼,我承認我所瞭解的並行化唯一的事情是它可以加速代碼,但並不是每一段代碼都可以並行,在嘗試並行編程之前是否應該知道任何基本知識?

任何幫助,將不勝感激。

回答

3

有幾件事情正在進行。首先,注意消耗內存的差異。這是一個跡象表明某些事情是錯誤的。通過將分配(您的zerosdzeros行)與核心算法分開,您將獲得更高的清晰度。但是,這種內存不太可能被分配使用;更可能的是,循環中的某些內容正在使用內存。請注意,您在左側描述了localpart,但您在右側使用原始DArray。這可能會觸發一些IPC流量。如果您需要調試內存消耗,請參閱ProfileView包。

其次,對於我來說,在進程中真正打破問題並不明顯。您正在循環遍歷整個數組的每個元素,而您應該讓每個工作循環遍歷它自己的數組。但是,您將遇到在localparts之間的邊緣處的問題,因爲更新需要相鄰的值。使用SharedArray會更好。

最後,啓動線程有開銷;對於小問題,你最好是而不是並行化,只使用簡單的算法。只有在計算時間達到數百毫秒(或更多)時,我纔會考慮進行並行化工作。

+0

那麼,正如問題中提到的,我的第二個樣本只是一個天真的試驗。 (我不明白這個教程的某些簡短的相應部分囧),可惜''SharedArray'不適用於Windows。問題中的樣本實際上是一個簡化的一維麥克斯韋方程求解器,當列表('ez','hy',並且會有更多的3D案例)變大時,[可能需要幾天的時間](http ://physics.stackexchange.com/q/106136/18778)。 – xzczd

1

N.B .:我是一個相對的Julia,FDTD,麥克斯韋方程和並行處理noob。

@tholy提供了一個很好的答案,提出了需要考慮的重要問題。

此外,Wikipedia Finite-difference time-domain method頁面提供了一些有關軟件包的參考資料和鏈接的良好信息,其中一些使用某種並行處理方式。

似乎許多FDTD的並行處理方法將物理環境劃分爲更小的塊,然後並行計算塊。一個複雜因素是邊界條件必須在相鄰塊之間傳遞。

使用你的玩具1D問題,我有限的朱莉婭的技能,我實現了玩具我的機器上使用兩個核心。這不是最通用的,模塊化的,可擴展的,有效的,也不是高效的,但它確實展示了並行處理。希望朱莉婭嚮導會改進它。

這裏是朱莉婭碼我用:

addprocs(2) 

@everywhere function ez_front(n::Int, ez::DArray, hy::DArray) 
    ez_local=localpart(ez) 
    hy_local=localpart(hy) 
    ez_local[1]=sin(n/10) 
    @simd for i=2:length(ez_local) 
    @inbounds ez_local[i] += (hy_local[i] - hy_local[i-1]) 
    end 
end 

@everywhere function ez_back(ez::DArray, hy::DArray) 
    ez_local=localpart(ez) 
    hy_local=localpart(hy) 
    index_boundary::Int = first(localindexes(hy)[1])-1 
    ez_local[1] += (hy_local[1]-hy[index_boundary]) 
    @simd for i=2:length(ez_local) 
    @inbounds ez_local[i] += (hy_local[i] - hy_local[i-1]) 
    end 
end 

@everywhere function hy_front(ez::DArray, hy::DArray) 
    ez_local=localpart(ez) 
    hy_local=localpart(hy) 
    index_boundary = last(localindexes(ez)[1])+1 
    @simd for i=1:(length(hy_local)-1) 
    @inbounds hy_local[i] += (ez_local[i+1] - ez_local[i]) 
    end 
    hy_local[end] += (ez[index_boundary] - ez_local[end]) 
end 

@everywhere function hy_back(ez::DArray, hy::DArray) 
    ez_local=localpart(ez) 
    hy_local=localpart(hy) 
    @simd for i=2:(length(hy_local)-1) 
    @inbounds hy_local[i] += (ez_local[i+1] - ez_local[i]) 
    end 
    hy_local[end] -= ez_local[end] 
end 


function fdtd1d_parallel(steps::Int, ie::Int = 200) 
    ez = dzeros((ie,),workers()[1:2],2) 
    hy = dzeros((ie,),workers()[1:2],2) 
    for n = 1:steps 
    @sync begin 
     @async begin 
     remotecall(workers()[1],ez_front,n,ez,hy) 
     remotecall(workers()[2],ez_back,ez,hy) 
     end 
    end 
    @sync begin 
     @async begin 
     remotecall(workers()[1],hy_front,ez,hy) 
     remotecall(workers()[2],hy_back,ez,hy) 
     end 
    end 
    end 
    (convert(Array{Float64},ez), convert(Array{Float64},hy)) 
end 

fdtd1d_parallel(1); 
@time sol2=fdtd1d_parallel(10); 

在我的機器(舊32位的2芯的筆記本電腦),這個水貨版本是不低於當地版本,直到ie快被設置爲某處大約在5000000

這是在朱莉婭學習並行處理一個有趣的案例,但如果我需要解決使用FDTD麥克斯韋方程,我會首先考慮那些已經現有的許多FDTD軟件庫。也許一個Julia包可以與其中一個接口。

+0

值得一提的是,該代碼僅適用於v0.3,'@ inbounds'也加快了代碼速度。在向並行版本添加'@ inbounds'之後,並行化代碼不會顯示出它的優勢,除非我在'100'周圍使用'steps',否則我無法很好地理解這種行爲。無論如何,感謝您的努力! – xzczd

+0

是的,我通常在朱莉婭回購的頭上。並行化(設置,消息傳遞等)有一些開銷,並且我的機器只有一個緩慢的總線到內核,核心必須共享。 – rickhg12hs

+1

雖然答案是「不是最一般的,模塊化的,可擴展的,有效的,也沒有效率的」,但是沒有人會忽略你的努力,而且,千金市骨,+50:D – xzczd

相關問題