999精品在线视频,手机成人午夜在线视频,久久不卡国产精品无码,中日无码在线观看,成人av手机在线观看,日韩精品亚洲一区中文字幕,亚洲av无码人妻,四虎国产在线观看 ?

MPI、OpenMP、Taichi并行編程語言探究

2022-06-18 08:00:16段皞一
電子元器件與信息技術 2022年4期
關鍵詞:進程程序

段皞一

浙江大學竺混1901班,浙江杭州,310058

0 引言

自1986年到2002年,短短幾年間,微處理器性能就以平均每年50%的進度得到顯著增強。這樣史無前例的性能提升,使得用戶和軟件開發人員只需要等待下一代微處理器的出現,就能夠獲得應用程序的性能提升。然而,2002年以后,單處理器的性能雖有提升,但速度降低到每年20%左右,這個差異是巨大的,因為如果以每年50%的速度提升,在10年里微處理器的性能會提升60倍,而以20%的速度,10年里只能提升6倍。

此外,性能提升速度的降低也在很大程度上影響著處理器的設計。到2005年,大部分主流微處理器制造商就已經放棄了更一步研發速度更快的單處理器芯片,而采用并行處理的辦法,即把多個完整的單處理器放置在一個集成電路芯片上,以此來快速提升微處理器性能。

這一辦法一經采用,效果顯著,有效解決了性能提升速度降低的問題,但卻給軟件開發人員產生了非常大的影響:許多串行程序要運行于單個處理器上,本身不會意識到有多個處理器存在,不能夠通過簡單地疊加處理器的辦法顯著提升性能。這就使得軟件開發人員開始關心并行處理、研制并行系統。

1 為什么要并行計算

1.1 為什么需要不斷提升性能

在過去幾十年當中,不斷提升的計算能力已經被當作部分快速發展領域的核心競爭力。伴隨著計算能力的提升,用它來輔助解決的問題也在增加,如氣候模擬、蛋白質折疊、藥物發現、能源研究、數據分析等,而這些問題需要更強大的計算能力。

1.2 為什么需要構建并行系統

隨著晶體管尺寸的日益減小,集成電路整體的發展速度越來越快,但是與此同時,由于功耗的相應增加,用空氣冷卻的集成電路的散熱能力已經達到了極限,這就導致了處理器在發展過程中出現了所謂的“功耗墻”。那么計算能力的提升該走向何處呢?答案就是并行處理。與研發更快、更復雜的單處理器相對比而言,將多個相對簡單的處理器放置于單個芯片上,即多核處理器還更加便捷一些。

1.3 為什么要編寫并行程序

為了讓一個程序能夠在多核處理器上運行,從而提高性能,就需要將串行程序改寫為并行程序,或者編寫一個翻譯程序將串行程序自動地翻譯成并行程序,這樣才能充分地利用多個核。很久以前,人們認為編譯器和運行時系統的某種神奇組合可以將現有的串行程序轉化為并行程序。但不幸的是,研究人員在自動將串行程序轉換成并行程序上鮮有突破。因為,串行程序的高效并行實現,可能不會通過發掘其中的每一個步驟的高效并行來獲得,相反,最好的并行化實現可能會通過一步一步回溯,然后發現一個全新的算法來獲得。所以,現在的并行程序從一開始就被寫成了并行程序。

例如,假設需要計算n個數的值再累加求和,串行累加求和代碼:

現在假設有個核,且遠小于,那么每個核能夠計算大約個數的值并累加求和,以得到并行累加和:

My_sum = 0;

My_first_i = …;

For (my_i = my_first_i; my_i <mylast)

每個核計算出各自的my_sum以后,將自己的結果值發送一個指定為master的主核,累加進而得到全局總和:

但是,這種計算全局總和的方法只是對串行求和程序的一般化,master核僅簡單重復了串行程序中基本的串行求和。顯然,master核承擔了更多的工作量,可以使用一種優化的方法:不再由master核計算所有部分和的累加工作,可以將各個核兩兩結對,通過樹形求和的方式共同計算形成一個全局總和,如圖1所示。

圖1 多個核共同計算形成一個全局總和

在1000個核的情形下,第一種方法需要999次接收和加法操作,而第二種方法則僅需要10次便可以完成,計算速度提高了100倍。上述內容已經涉及初步的并行思維。

2 并行編程語言環境

MIMD系統,即多指令多數據流(multiple instruction, multiple data, MIMD)系統,可以同時執行多個指令流,這些指令流分別對不同數據流進行操作。最新的多核計算平臺就屬于MIMD的范疇,例如Intel和AMD的雙核處理器等都屬于MIMD。MIMD系統支持同時多個指令流在多個數據流上操作,因此MIMD系統通常包括一組完全獨立的處理單元或者核,每個處理器單元或者核都有自己的控制單元和ALU。如前所述,MIMD系統主要有兩種,分別是共享內存系統、分布式內存系統。

2.1 分布式內存系統

該系統是由網絡連接的核-內存對的集合組成,內存與核相關聯,僅能通過相應的核進行訪問(如圖2所示)。

圖2 一個分布式內存系統

2.2 共享內存系統

該系統是由核的集合組成,所有核均連接到一個全局訪問的內存,每個核都可以訪問內存的任何位置(如圖3所示)。

圖3 一個共享內存系統

綜上,并行編程環境不同,變量的使用域是不同的,數據訪問的機制也將不同,從而導致兩種環境各自編程語言的并行化設計不同。

3 用MPI進行分布式內存編程

使用分布式內存系統進行編程時,各個核之間的內存是隔離的,從而核之間如果需要協同合作,共同計算一個任務,就必須要使用消息傳遞。在這一程序中,運行在一個核-內存對上的程序通常被稱之為一個進程。兩個進程可以通過調用函數來實現通信:一個負責調用發送函數,另一個負責則調用接收函數。消息傳遞接口(MPI)是一個可以被C、C++和Fortran程序調用的函數庫,可以使用mpicc編譯MPI程序,并通過mpiexec運行[1]。

3.1 編譯和運行

許多系統都用稱為mpicc的命令來編譯程序:$ mpicc -g -Wall -o mpi_hello mpi_hello.c許多系統還支持用mpiexec命令來啟動程序:

$ mpiexec -n <number of processes> ./mpi_hello

3.2 數據劃分和分配

3.3 通信

要想從一個MPI進程發送數據給另一個進程,可以調用MPI_Send函數,而MPI_Recv函數用來接收消息。MPI_Send函數的參數描述了數據的內容和它的目的地,而MPI_Recv函數的參數描述了用于存儲接收到數據的緩沖區以及應該從哪里接收數據。MPI_Recv是阻塞的,即調用MPI_Recv后,直到消息收到之前該函數是不會返回的。

3.4 MPI的梯形積分法

編寫MPI程序時,非常重要的一點是區分局部變量和全局變量。局部變量只作用于定義它的那個進程,而全局變量則作用于全部進程,下面在用MPI來實現梯形積分法的例子中,梯形的全部數量是一個全局變量,每個進程區間的左、右端點是局部變量。

3.4.1 計算任務分析

圖4 梯形積分法

由于n個子區間是等分的,因此如果兩條垂線包圍區域的邊界分別為x=a和x=b,那么,

因此,如果稱最左邊的端點為x0,最右邊的端點為xn,則有,

3.4.2 并行程序設計

對梯形積分法進行并行化。可以通過四個基本步驟來設計出一個并行程序:①將問題的解決方案劃分成多個任務;②在任務間識別出需要的通信信道;③將任務聚合成復合任務;④在核上分配復合任務。

在劃分階段,能夠識別出任務主要有2種:一是獲取單個矩形區域的面積,二是計算這些區域的面積之和。在這之后再通過通行信道把每個第一種任務與一個第二種任務連接起來,如圖5所示。

圖5 梯形積分法的任務與通信

圖6 樹形結構全局求和

鑒于各種可能性都有可能會隨時發生,依賴MPI程序員可以在任何情境下均能第一時間編寫出最佳的全局求和函數是不太可能實現的,也是不合情理的。因此,MPI中包含了全局求和的實現,這就可以讓程序員不用陷于無止境的程序優化的泥沼。很顯然的是,“全局優化函數”需要進行通信,但它與MPI_Send函數和MPI_Recv函數這樣的兩兩匹配不同,可能會涉及多個進程,這樣的通信也被稱為集合通信。兩個常用的集合通信函數是MPI_Reduce和MPI_Allreduce,一個將全局操作的結果存儲到指定的進程,另一個將結果存儲到通信子中的全部進程中。在MPI中,一個通信子是一組進程的集合,該集合中的進程之間可以相互發送消息;MPI程序啟動后,MPI創建所有進程組成的通信子,稱為MPI_COMM_WORLD。

3.5 集合通信函數

MPI還提供了很多重要的集合通信函數。

上述集合通信為MPI的并行性提供了很好的支持。

3.6 通信死鎖

由于MPI消息接收函數MPI_Send既可以阻塞也可以緩沖輸入,如果一個MPI程序的正確行為取決于MPI_Send正在緩沖的輸入,則它是不安全的,這經常發生在多個進程第一次調用MPI_Send、然后調用MPI_Recv的情況。如果MPI_Send不采用緩沖方式,那么會一直阻塞直到相應的MPI_Resv被調用,然而這個情況卻永遠不會發生,例如,進程0和進程1想要相互發送消息,兩者都是先發消息然后開啟接收,進程0會等待進程1調用MPI_Recv,而進程1則一直阻塞在MPI_Send,等待進程0調用它的MPI_Recv,這樣互相等待的狀態就形成了死鎖,雙方都阻塞并等待永遠不會發生的事件發生。

一個不安全的MPI程序可以通過多種方法變為安全的,程序員可以調度MPI_Send和MPI_Recv使得某些進程先調用MPI_Send,而其他剩下的進程先調用MPI_Recv。另外,還可以使用MPI_Sendrecv或者MPI_Sendrecv_replace,這些函數僅僅發送和接受一次消息,各自保證不會崩潰或者死鎖。

3.7 活躍通信

MPI范式傳統上是基于雙側操作的,即每個數據傳輸都需要一個明確的發送和接收操作。這種方法對于相對簡單的代碼來說效果很好,但是對于復雜的問題來說,就很難協調所有的數據移動。此外,前面也提到了采用阻塞的雙側操作勢必會帶來死鎖問題。簡化的方法之一是使用活躍通信(active message)。這在Charm++包中被使用。

通過主動消息,一個處理器可以向另一個處理器發送數據,而不需要第二個處理器做明確的接收操作。相反,接收者聲明處理傳入數據的“方法”,而發送處理器則用它想發送的數據調用這個方法。由于發送處理器實際上是激活了另一個處理器上的代碼,這也被稱為遠程調用(remote method invocation)。這種方法的一個很大的優點是,通信和編譯的重疊變得更容易實現。

作為一個例子,考慮一個對角矩陣向量乘法的運算,MPI代碼可以是這樣的:

有了活躍通信,這看起來就像:

3.8 通信延遲的緩解

MPI進行并行編程的時候,需要頻繁調用消息通信函數,而處理器間的通信通常很慢,比單個處理器上的內存數據傳輸得要慢,而且比對數據的操作要慢得多。從程序員的角度出發,主要有兩種方法能夠緩解通信帶來的延遲問題。第一種方法是在設計MPI并行程序時,考慮網絡流量與“有用”操作的相對數量,即每個處理器必須有足夠的工作來抵消通信;第二種緩解通信相對緩慢的策略是安排程序,使通信實際發生在一些計算正在進行的時候。

4 用OpenMP進行共享內存編程

理論上來講,共享內存系統中的任意處理器核均可以訪問所有的內存區域。因此,協調各個處理器核工作的方法之一,就是把某個內存區域設為“共享”,這是并行編程中常見的方法。共享內存編程規避了很多問題。結合之前的MPI編程語言的分析,可以發現在進行并行編程的時候,需要頻繁地調用消息通信函數,而處理器間的通信通常很慢。雖然有一些方法能夠對這種延遲進行緩解,但是始終無法徹底解決問題。而在共享內存系統下,這根本不是問題[4]。

或許有人會問,既然如此,為什么不讓所有的并行編程都使用共享內存環境呢?接下來探討在OpenMP共享內存編程范式的過程中,將會發現共享內存會引發另外的問題。

4.1 OpenMP和Pthreads的對比

雖然都是針對共享內存編程的API,它們二者卻存在很多本質上的差異。Pthreads要求程序員明確每個線程的行為,但是OpenMP有時則允許程序員只需要簡單地聲明一塊代碼塊應該并行執行,由編譯器和運行時系統來具體選擇哪個線程去執行哪個任務。這也就意味著兩者還有另外一個不同之處,即Pthreads是一個可以被鏈接到C程序的函數庫,所以說只要系統有Pthreads庫,Pthreads程序就能夠被任意C編譯器使用。相反,OpenMP則要求編譯器必須支持某些操作,所以完全有可能出現使用的編譯器不能將OpenMP程序編譯成并行程序的情況。

這些不同也說明了為什么共享內存編程會有兩個標準API:Pthreads更底層,并且提供了編寫任何線程行為的能力。但是,這個功能有一定的代價:每個線程行為中的每一個細節都等待著程序員去定義。相反,OpenMP最重要的特色之一就是它的設計使得程序員可以逐步并行已有的串行程序,而不是從零開始編寫并行程序。

4.2 OpenMP的編譯和運行

在C和C++中,有一些預處理指令pragma。在系統中加入預處理器指令一般是用來允許輸入不是基本C語言規范部分的行為。不支持pragma的編譯器則會忽略掉pragma指令提示的那些語句。而預處理指令pragma omp則告訴編譯器接下來的代碼塊需要使用OpenMP并行策略執行。

下列是一個使用OpenMP的“hello, world”程序:

為了用gcc編譯這個程序,需要包含-fopenmp選項:

$ gcc -g -Wall -fopenmp -o omp_hello omp_hello.c

為了運行程序,在命令行中明確線程的個數。例如,希望有四個線程運行程序,就輸入:

$ ./omp_hello 4

如上述代碼所示,OpenMP像Pthreads程序一樣,也是經常在命令行里指定線程數。和Pthreads做對比可以發現,Pthreads需要寫許多代碼來派生和合并多個線程,為每個線程分配存儲空間,使用一個for循環來啟動每個線程,并使用另一個線程來終止這些線程。由此可見,OpenMP比Pthreads層次更高。

4.3 OpenMP組成及并行機制

編譯指導(compiler directive)、運行庫(runtime library)和環境變量(environment variables)是構成OpenMP的三個重要組成部分,其語言模型采用的是fork-join執行模式。開始時只存在一個主線程,當需要進行并行計算時,便會派生出若干個分支線程來執行并行任務。當并行代碼執行完成之后,分支線程會合,然后再將控制流程交給單獨的主線程。也就是說,OpenMP是基于派生/連接(fork/join)的編程模型。fork/join的并行機制如圖7所示。

圖7 fork/join

OpenMP編程模型以線程為基礎,通過編譯制導指令制導并行化,編譯制導、API函數集和環境變量等編程要素能實現并行化控制。

4.4 OpenMP編譯制導指令

編譯制導指令以#pragma omp開始,后邊跟具體的功能指令,格式如:#pragma omp 指令[子句[,子句]…],使用#pragma omp parallel是用來表明之后的結構化代碼塊需要被多個線程并行執行。這順應了C語言是結構化編程語言的特性。但是值得注意的是,這個代碼塊里面允許調用exit函數,只是單純地禁止分支語句進入或者離開結構化代碼塊。

#pragma omp parallel是最為簡單的、基礎的parallel指令,但是其線程數量由運行時系統決定的算法是十分復雜的,具體細節詳見OpenMP標準。

當代碼執行完畢后,有一個隱式路障——完成代碼塊的線程要等待線程組中的其他線程都完成代碼塊。只有當所有線程均執行了并行代碼塊,從線程才會終止,然后主線程繼續執行之后的語句。每個線程都有自己的堆棧,在執行并行代碼塊時,線程將在堆棧中創建自己函數里定義的私有變量。

4.5 OpenMP的梯形積分應用

按照之前的經驗對典型的梯形積分法進行并行化,主要涉及兩類任務:單個梯形面積的計算;梯形面積的求和。其中,梯形面積的求和很容易想到的方法就是使用一個共享變量記錄所有線程的和。

global_result += my_result

然而,這就會導致訪問競爭問題。當多個線程試圖訪問同一個共享資源,且其中有訪問會更新該共享資源時,便可能會造成系統出錯。而上面的問題是每個線程把自己的result加到共享變量上,顯然會導致寫覆蓋的問題(WAW/RAW/WAR等),因此需要有一個機制確保每次只有一個進程能夠進入臨界區。在Pthreads中,使用互斥量或者信號量,而在OpenMP中,使用的是critical命令,這條指令告訴編譯器需要安排線程對之后的代碼塊進行互斥訪問:

# pragma omp critical

global_result += my_result

4.6 變量的作用域

梯形積分程序中,在parallel塊中被每個線程調用的Trap函數內部使用了本地變量h, x, my_result, local_a等,屬于被每個線程使用的私有變量,在線程的私有棧中分配。鑒于此,這類變量只能夠被單個線程訪問,擁有私有作用域。

而main函數中聲明的變量是所有parallel指令啟動的線程都能夠訪問的,因此這類變量的缺省作用域是共享的。

事實上,已經隱式使用了每個在線程組中的線程可以從Trap的調用中得到的a, b, n的值,因為這個調用發生在parallel塊里,所以當它們的值被賦予對應的形式參數時,每個線程都能夠訪問a,b,和n。

在Trap函數中,雖然global_result_p是私有變量,然而它是指針,引用了外部的共享變量,因此,每個線程都能夠對該指針指向的地址的值做互斥的增加,從而達到求和的目的。

對共享變量的改寫是互斥的,但是有些時候,不希望臨界區的代碼塊串行執行,因為這樣可能會讓性能大大降低,所以從編程的角度去解決這個問題,即盡量創建私有變量進行并行處理,最后再將每個線程得出的私有變量結果進行互斥處理,比如簡單的求和等,而不是將大算量壓到共享變量上。

可喜的是,OpenMP提供了一個更為清晰的方法用來規避大算量任務的串行執行。上述例子便能將global_result變量定義為一個規約變量。

另外,常用的編譯指導語句還有parallel for語句,使用該語句將對循環語句for進行線程并行。但是值得注意的是,OpenMP編譯器不檢查被parallal for指令并行化的循環所包含的迭代間的依賴關系,這些都需要程序員自主完成這一操作。只有每次循環是獨立的,不需要依賴之前的迭代結果的for循環,才是能夠被parallel for正確執行并行的。

5 混合共享/分布式內存計算

5.1 MPI的優勢與劣勢

優點:它能夠在集群上使用,也能夠在單核/多核CPU上使用,適用范圍比較廣,能協調多臺主機間的并行計算,所以說并行規模上的可伸縮性很強,能在個人電腦到世界TOP10的超級計算機上使用。

缺點:一是基于消息傳遞,需要顯示劃分和分布計算任務,顯示進行消息傳遞與同步,且不易增量開發串行程序的并行性;二是使用進程間通信的方式協調并行計算,造成并行效率較低、內存開銷大、不直觀、編程麻煩等一系列問題。

5.2 OpenMP的優勢與劣勢

優點:編譯器依照程序中添加的pragma指令,自動將程序并行處理,使用OpenMP降低了并行編程的難度以及復雜度;使用共享存儲模型,程序員不需要進行數據劃分與分布,開發并行程序比較容易;更適合于SMP系統[“對稱多處理”(Symmetrical Multi-Processing)簡稱SMP,是指在一個計算機上匯集了一組處理器(多CPU),各CPU之間共享內存子系統以及總線結構。它是相對非對稱多處理技術而言的、應用十分廣泛的并行技術];主要面向循環級的并行開發,能比較便捷地實現增量性的并行化。

缺點:作為高層抽象,OpenMP并不適用于需要復雜的線程間同步和互斥的場合;不可以應用于非共享內存系統;主要開發循環級的并行程序,因此它對某些應用并不適合;OpenMP的編寫、正確性調試和性能調度則比較復雜。

5.3 混合并行編程概念

并行編程吸取了綜合分布式和共享式各自的優點進行混合編程。

一個常見的集群設置使用分布式內存節點,每個節點包含幾個彼此之間共享內存的插槽。使用MPI在節點之間進行通信,使用OpenMP在節點上進行并行化,這樣就實現了混合編程[5]。

盡管MPI進程之間消息傳遞看起來比共享內存的通信開銷更大,但當MPI的優化版本檢測進程在同一個節點時,就會采取時間開銷更小的數據拷貝以代替通信。

使用混合并行編程帶來了諸多好處。如果代碼的某一部分需要每個進程有更多的內存,那么OpenMP方法可以限制這一部分的線程數量。另一方面,對線程的靈活處理會產生一定的操作系統開銷,而MPI的固定進程是沒有這種開銷的。

此外,混合方法能夠捆綁消息。例如,如果一個節點上的兩個MPI進程分別向另一個節點上的兩個進程發送消息,就會有四條消息。在混合模型中,這些消息將被捆綁成一條消息。

6 Taichi編程語言

前面講述的并行編程范式本質上是基于傳統的C的并行庫展開的。可是很多時候,程序員可能會更加喜歡Python,因為它擁有面向對象,語法更加簡潔,具有很多現成工具包的優勢,大大提升了開發效率。

于是矛盾就在這里產生了,由于Python是解釋型的語言,盡管開發過程十分友好,但是從性能的角度出發,完全是沒法和編譯型的C語言相提并論的。所以應用Taichi將寫出的Python代碼高性能地運行。

6.1 Taichi編程語言簡介

Taichi是一種嵌入 Python 中的DSL(領域特定語言,即Domain-Specific Language的縮寫,相當于C語言中的 float)。Taichi是一門面向數據的程序設計語言,其中(稠密、稀疏)張量是第一公民(First-class Citizen)。它會把自定義函數編譯成機器指令碼,在CPU或GPU上并行執行,從而既保證了性能,又保證了生產力,但需要根據硬件平臺進行初始化:

# 在 GPU 上運行,自動選擇后端

ti.init(arch=ti.gpu)

# 在 GPU 上運行,使用 NVIDIA CUDA后端

ti.init(arch=ti.cuda)

# 在 GPU 上運行, 使用 OpenGL 后端

ti.init(arch=ti.opengl)

# 在GPU上運行,使用蘋果Metal后端(僅對OS X)有效

ti.init(arch=ti.metal)

# 在 CPU 上運行(默認)

ti.init(arch=ti.cpu)

6.2 Taichi編程語言剖析

下面從官方文檔提供的分形程序,剖析Taichi編程語言。

6.2.1 張量

6.2.2 函數與內核

Taichi的并行計算發生在Taichi的內核(kernel)中,內核的參數必須顯示指定類型。Taichi內核與函數中所用的語法,看起來和Python的很像,然而Taichi的前端編譯器會將其轉換為編譯型,靜態類型,有詞法作用域,并行執行且可微分的語言。

Taichi的函數可以被Taichi內核和其他Taichi函數調用,使用關鍵字ti.func來進行定義。

任何被@ti.kernel和@ti.func修飾的函數體都處于Taichi作用域中,這些代碼會由 Taichi編譯器編譯。而在Taichi作用域之外的就都是Python作用域了,它們是單純的 Python代碼。

如果用CUDA做類比,ti.func就像是__device__,ti.kernel就像是__global__。

6.2.3 并行執行的for循環

最外層作用域的for循環是被自動并行執行的。Taichi的for循環具有兩種形式,即區間for循環和結構for循環。

6.2.3.1 區間for循環

區間for循環和普通的Python for循環沒多大區別,只是Taichi最外層的for會并行執行而已,但區間for循環可以嵌套。

6.2.3.2 結構for循環

結構for循環是Taichi稀疏計算[Sparse computation (WIP)]的關鍵,它只會遍歷稀疏張量中的活躍元素。對于稀疏張量而言,所有元素都是活躍元素。這在遍歷張量元素的時候很有用,類似深度學習時對張量的處理。

6.3 Taichi編程語言性能

眾所周知,圓周率是一個常數,約為3.1415926,可以用下面這個公式計算:

6.3.1 Python計算圓周率

寫一個Python程序來計算:

得到如下輸出:

PI = 3.1415926385900446

14.5 sec

6.3.2 C語言計算圓周率

同樣的任務,嘗試使用C語言進行計算:

運行結果:

PI = 3.141592638590045

1.348 sec

顯然,解釋型的Python語言,性能上比編譯型的C語言差了許多。

6.3.3 Taichi計算圓周率

還是圓周率的例子,要用 Taichi 編譯一個函數,以便高性能執行,只需在前面加一個@ti.kernel的裝飾器;另外Taichi 會默認以 CPU 模式運行,如果指定為 GPU ,結果會更快:

運行結果:

[Taichi]mode=release

[Taichi]version 0.6.6, supported archs:[cpu,cuda, opengl], commit 7d76c01c, python 3.8.2

PI = 3.1415982246398926

1.56 sec

從以上的例子可以看到,通過Taichi的使用,可以在Python代碼里寫出接近編譯型語言的性能,這大大提升了Python作為解釋語言的運算能力,特別是大規模并行時的運算能力。

6.3.4 Taichi計算圓周率代碼分析

@ti.kernel:

一切以@ti.kernel修飾的函數都會被Taichi編譯。

def calc_pi() -> ti.f32:

Taichi是靜態類型的,因此需要指定函數的返回類型。

for i in range(66666666):

編譯器會自動把 for 循環分配到多個線程,并行執行,線程數量取決于你CPU的核數。而用戶完全不必擔心 for 循環的展開,編譯器會處理一切優化問題。

sum += pow(-1.0, i) / n:

Taichi可以保證+=是原子操作,不會出現多線程數據競爭的問題。

sum = 0.0:

可見,雖然代碼被傳遞給了Taichi編譯器來編譯,但大體上依然遵循Python的語法。

7 結語

MPI和OpenMP是基于C/C++語言的兩個并行編程語言API,但并行編程環境不同,一個是分布式編程,一個是共享式存儲編程,因此編程的特性、并行的架構有很大的區別。在超算并行優化領域,可以使用混合編程架構綜合MPI和OpenMP二者的優點,規避二者的缺點,進行高效的并行計算。

上述編譯型編程語言架構的并行很早就已經提出,并且已經發展較為成熟。而近年來像Python這樣的解釋型語言熱度逐年上升,成為眾多程序員愛不釋手的開發環境,因為它擁有面向對象,語法更加簡潔,具有很多現成工具包的優勢,大大提升了開發效率。但是,由于Python是解釋型的語言,從性能上講并不出色,通過并行的方式對Python進行性能的優化,是個很好的思路。Taichi是一個嵌入在Python中的領域特定語言,在代碼的循環部分使用CPU/GPU進行并行計算,其他部分還是使用Python解釋運行,既保證了性能,又保證了生產力。Taichi是在前述MPI、OpenMP,包括Pthreads、Cuda等并行架構基礎上,在解釋型Python語言上對并行的探索、深耕和遠拓,非常具有前瞻性。

猜你喜歡
進程程序
債券市場對外開放的進程與展望
中國外匯(2019年20期)2019-11-25 09:54:58
試論我國未決羈押程序的立法完善
人大建設(2019年12期)2019-05-21 02:55:44
失能的信仰——走向衰亡的民事訴訟程序
“程序猿”的生活什么樣
英國與歐盟正式啟動“離婚”程序程序
環球時報(2017-03-30)2017-03-30 06:44:45
創衛暗訪程序有待改進
中國衛生(2015年3期)2015-11-19 02:53:32
恐怖犯罪刑事訴訟程序的完善
我國高等教育改革進程與反思
教育與職業(2014年7期)2014-01-21 02:35:04
Linux僵死進程的產生與避免
男女平等進程中出現的新矛盾和新問題
主站蜘蛛池模板: 国产精品深爱在线| 992Tv视频国产精品| 谁有在线观看日韩亚洲最新视频| 欧美日韩在线成人| 亚洲午夜天堂| 在线国产欧美| 国产二级毛片| 欧美精品在线免费| 成年女人18毛片毛片免费| 日韩无码视频播放| 免费人成视网站在线不卡| 喷潮白浆直流在线播放| 国产黄色视频综合| 国产精品妖精视频| av在线5g无码天天| 欧美成人午夜视频免看| 亚洲第一页在线观看| 99er精品视频| 久久久久久午夜精品| 久久亚洲日本不卡一区二区| 五月天婷婷网亚洲综合在线| 国产主播喷水| 91精品情国产情侣高潮对白蜜| 欧美激情成人网| 欧美笫一页| 91色综合综合热五月激情| a级毛片网| 亚洲欧美日韩中文字幕在线一区| 国内毛片视频| 91麻豆精品视频| 青青青国产视频手机| 伊人91在线| 在线看国产精品| 国产农村1级毛片| 婷婷六月综合网| 在线看片国产| 激情無極限的亚洲一区免费| 成人免费一级片| 亚洲av日韩综合一区尤物| 国产在线精品人成导航| 国产成人精品一区二区不卡| 国产精品欧美激情| 久久a级片| 免费无码又爽又黄又刺激网站| 91在线国内在线播放老师 | 亚欧乱色视频网站大全| 国产区精品高清在线观看| 欧美激情,国产精品| 亚洲三级视频在线观看| 免费人欧美成又黄又爽的视频| 欧美三级不卡在线观看视频| 亚洲成a人片在线观看88| 亚洲精品日产精品乱码不卡| 日本草草视频在线观看| 国产第八页| 91久久夜色精品| 91亚洲精选| 五月六月伊人狠狠丁香网| 久久亚洲日本不卡一区二区| 婷婷开心中文字幕| 色天堂无毒不卡| 国产99精品久久| 中国毛片网| 2022国产91精品久久久久久| 国产精品网曝门免费视频| 在线永久免费观看的毛片| 丁香综合在线| 国产精品30p| 亚洲午夜天堂| 国产麻豆永久视频| 久久久久九九精品影院| 精品三级网站| 国产精品3p视频| 日韩精品亚洲一区中文字幕| 国产高清又黄又嫩的免费视频网站| 99激情网| 国产一级二级三级毛片| 国产亚洲成AⅤ人片在线观看| 日本欧美视频在线观看| 欧美成人国产| 久久美女精品| 亚洲人成网站18禁动漫无码|