• 沒有找到結果。

一次演化的時距(Time Step),由 CFL condition 決定,其基本概念是訊息最 大的傳遞速度是聲速加上流速,在一次演化裡,我們不容許任何訊息走超過一 個格點,因為每次演化我們模擬的訊息傳遞也只會影響到隔壁的網格。於是對 於某格點所能接受的最大時距是∆ ∆ ,其中∆ 是演化時距,Vmax

Vx,Vy,Vz三者取最大值,Cs是該網格的聲速,可由方程式 求得,∆ 是網 格寬度。詳細的數學分析可參考 A Primer on Eulerian Computational Fluid

Dynamics for Astrophysics [3]。

我們必須找到一個適當的時距,滿足每個格點允許的時距限制,由於在本 程式的架構下,相鄰兩層的網格,細網格的∆ 與∆ 都恰好粗網格的一半。在程 式裡,我們定義最細網格的寬度為單位長度,於是各階層網格的寬度為

∆ 2 ,各階層網格的時距為∆ 2 ∆ ,其中lv 是各 階層的階級,ML 是最細格點的階級,階級越大代表網格越細。而∆ 可由圖 2.7 的虛擬碼求出。在實作上我們會對演化時距加個安全系數,因為在最粗格點 演化一次(Global Time Step)的時間裡,細格點會使用相同的時距演化多次。

15

圖 2.7: 程式虛擬碼

圖 2.8: 程式虛擬碼

16

2.6 演化

在圖 2.2 裡,Intergration 函式就是將流體演化到下一個時刻點的主要函式,也 是本程式中流體模擬的核心。函式內的基本步驟已經在 2.2 節裡做過說明,在本小 節裡,我們將更深入的介紹 Intergration 裡各個子函式。

2.6.1 演化簡介

圖 2.8 是 Intergration 的虛擬碼,其中 evolve 函式就是演化每一層網格的函式,

fixup 函式就是將細格點算出來的值往上修正粗的格點,refine 函式就是進行每一 層網格調變的函式。其中 refine 函式的重點已經在 2.4 節說明過了。

分別為顯示卡的主記憶體(global memory)、共享記憶體(shared memory)、與暫存器 (register)。在 CPU 裡也有類似的架構,分別為主記憶體(main memory)、快取 (cache)、與暫存器。在顯示卡中讀取主記憶體的延遲(latency)是讀取共享記憶體的 數百倍之多,約為 200~400 個時脈週期。所以要將顯示卡的計算能力完全發揮,

17

一定得要善用共享記憶體。

一張顯示卡內有多個串流處理器,在 CUDA 的架構底下,將 8 個串流處理器 組成一個複合處理器(multiprocessor),每個複合處理器擁有一個大小為 16 kb 的共 享記憶體(shared memory),提供給這 8 個 stream processors 作更快速的存取。不同 的複合處理器是不能互相讀取其它複合處理器的共享記憶體。

18

論。

為了增進程式效率,我們注意到產生小片的過程,都是由一個父小片產生八 個相鄰的子小片(可參考圖 2.1),為了節省邊界值的處理,我們將八個相鄰的小片 視為一個更大的小片,一起送入顯示卡進行演化,增進程式效率。

由於顯示卡和 CPU 是兩個獨立的運算核心,CUDA 支援兩者分別進行獨立的 運算。所以我們將大量的小片拆成多組小片,分批送入顯示卡。讓顯示卡進行演 化運算的同時,CPU 可以處理下一批被送入的小片之邊界值,達成程式的最佳化。

而在本程式裡,邊界值的處理所花費的時間正巧與 GPU 的進行演化所花費的時間 相近,在這樣的功能底下,我們將程式的效率提高了兩倍。

2.6.3 向上修正

不同粗細的運算,由於誤差的關係,往往不盡相同,所以我們必須將細格點 所得到的結果,對粗格點修正。所需要的修正主要分為兩種,一個是擁有子小片 的小片,其格點的值,會完全被更細格點的平均所取代。另外是擁有粗細邊界的 小片,粗小片與細小片間的流量必須要修正,讓守恆量維持守恆。

如果使用 Error Estimate(見 2.4.1 節)的方法調變網格粗細,則可在此時進行粗 細格點計算誤差的比較,並標記誤差大的區域,在調變時產生更細的網格點。

關於粗細邊界流量的修正,我們必須另外建立一個新的記憶體空間,在每次 演化時記錄粗細邊界的流量。而在顯示卡運算時,由於每個小片的邊界值在經過 運算之後,其記憶體空間便空了出來,恰好可存放各邊界的流量,而不需要在顯 示卡內另外宣告記憶體做儲存。

19

相關文件