加入RUN!PC粉絲團
最近新增的精選文章
 
最多人點閱的精選文章
 
 
精選文章 - 開發技術
分享到Plurk
分享到FaceBook
 
Visual Studio 2010 ─ 技術核心(4)
大幅降低平行運算開發的門檻
文/黃昭仁

還在土法煉鋼的開發運行於多核心系統的程式嗎?本文將帶領你利用Microsoft Visual Studio 2010內建的完整函式庫,以快速且有效的開發方式,發揮多核心的運算效能。

就在Windows作業系統甫剛推出的時候,開發人員最期待與關注之處,莫過於多執行緒程式撰寫方面的技術了。我們可以想像,在硬體還相當昂貴的時代,每台個人電腦搭配的CPU都是單核心,意即在一個時間點中,CPU只能處理一件事情(運算),就如同圖1的示意圖。

圖1:單執行緒工作模式。


在圖1中,我們可以將工作簡單的分為進行數學運算所耗費的時間「C」,以及資料在記憶體中搬移所需的時間「M」,所以我們可以知道,若程式碼需要大量的運算時間,例如執行數百萬次的數學運算,則只能一筆一筆序列式的進行。而多執行緒技術的出現,說穿了其實是一種分時分工的演算法實現,其多執行緒的工作模式,可以經由圖2來了解。

圖2:多執行緒的工作模式。


分工器會依照開發人員所設定的執行緒優先權(Thread Priority),將原本需要一筆一筆序列化進行的工作,藉由分工器不斷的在執行緒間快速的切換工作權,讓每個工作執行緒輪流使用CPU資源,達到「近似同時」進行運算的目的。


徒手開發多執行緒程式的難度
然而多執行緒架構的系統開發雖然強大,但是往往開發人員都要付出相當的代價。就本質上來看,分工器是將CPU的資源進行共享,所以原本運算所需要的總體時間,並不會因此減少,甚至由於多執行緒之間進行切換時,有所謂的Context Switch消耗時間,所以在單核心的條件下,以同樣的數學運算量來說,序列式的單執行緒運算方式,通常都會比多執行緒運算要來的快速。

目前市面上不論是個人端的電腦硬體配備,或是企業端的伺服器主機,皆已進入所謂的多處理器、多核心的時代,能否有效的利用強大的硬體運算能力,是身為一個專業的開發人員無法不去面對的重要議題。而多執行緒儼然成為開發人員必備的「傳統的技藝」。

會稱為傳統的技藝,是因為在不同的執行緒之間,會需要進行資料的交換、執行緒間執行的優先順序、執行緒間的相互等待等,一般來說,開發人員會實作所謂的Reference Count、Thread Pool、Task Scheduler、Resource Manager等機制來維持系統正常運作,這不僅使得多執行緒的系統建置難度加高,而且在後續的維護及除錯上,也更加的複雜困難,往往系統初始的架構或機制設計不良,就會導致如惡夢般的災難。

舉例來說,要開發一個大型多工系統,其硬體配備有如圖3的強大,單是CPU就有128個可供程式開發人員使用,要如何有效的利用、發揮系統資源,以期能達到系統100% 的運行效益呢?這時候就得使用「傳統的技藝」來進行多執行緒程式開發,必須面對一堆多執行緒程式撰寫所需要建立的複雜機制。

圖3:大型多工系統的硬體配備多核心資源。



Visual Studio 2010內建平行運算函式庫
事實上,上述的多執行緒程式架構也算是平行運算的一種,在Visual Studio 2010中已提供了所需的機制,來簡化開發平行運算系統時的繁雜步驟,其函式庫架構如圖4所示。透過高度封裝過後的類別架構,開發者就可以在Visual Studio 2010環境中,簡單的呼叫來進行系統的建置;而這些機制的底層技術,即為傳統的技藝,Visual Studio 2010已經將原本複雜的事情,簡化成開發人員只要專注在需要解決的問題上,大大降低了以往開發多工系統的複雜度。

圖4:Visual Studio 2010的平行運算架構。



實際體驗簡易的平行運算開發
若你經過實作,在Visual C++程式中運用Visual Studio 2010所內建的平行函式庫,相信你也會跟筆者一樣,驚艷於Parallel Patterns Library(PPL)所提供的「parallel_for」。

這是一個矩陣相乘的函式,在一般應用數學計算的場合很常見到,程式實際在執行階段的時候,若此函數被呼叫到,我們可以透過作業系統提供的工作管理員(Task Manager)來觀察,在函式運行的時間內,會有一顆CPU的資源耗用率飆高(如圖5),而其他的CPU則不為所動,這也就說明了,這是一個單執行緒(Single Thread)運算的過程。

圖5:只有耗用單顆CPU資源。


此時若要運用parallel_for,只要在程式中引用「ppl.h」這個檔頭:「#include 」,並且把程式加以改造。將原本程式迴圈最外層的變數「i」換置為「parallel_for」函式樣板,接著程式在執行的過程中,再次透過工作管理員觀察,如圖6,系統已經把所有的CPU都用上了,一起加入平行計算矩陣相乘的工作中。

圖6:平均使用到CPU資源。


這真是太神奇了!令筆者驚艷的是,過去我們在進行一連串複雜的數學運算時,了不起就是把運算的整個流程,當成一個單執行緒流程來進行呼叫,另外再使用開發多執行緒的技術,來將此運算流程改成支援多個執行緒的流程。

舉例來說,語音辨識或影像辨識這些演算法需要大量的數學運算,而且在整個過程中又分成許多道的數學轉換,在電腦硬體進行多處理核的這個世代,若要將這些過程中的迴圈、函式、資料交換…等,轉換為平行處理的話,不但工程浩大且複雜度也過高。如今若可以善加使用高度封裝好的平行運算函式庫,對開發人員的負擔就可以降低許多,而生產力自然也會相對提昇。


善用除錯工具
此外,程式開發過程中需要經常使用的除錯方式,除了一般常用的Threads Window、Call Stack Window等搭配中斷點來進行,在Visual Studio 2010中還增添了許多工具,像是平行工作(Parallel Tasks)及平行堆疊(Parallel Stack)視窗,如圖7與圖8所示,開發人員可以進一步觀察到應用程式執行階段時,執行緒間的相依關係,及相關的執行緒堆疊,而且若因為設計不良所導致死結(deadlock)的發生,也可以利用這些工具來發現。

圖7:平行工作視窗。



圖8:平行堆疊視窗


之後還可以透過並行效能分析器(Parallel Performance Analyzer)的協助,分析出目前應用程式的處理器狀態、執行緒狀態、整體運行時間等有用的資訊,如圖9所示。

圖9:並行效能分析器。



多點觸控輸入和Ribbon介面之應用程式之開發
雖然網路上常常會有「MFC已死」的聳動標題,但是伴隨著Visual Studio 2010之推出,MFC有如浴火鳳凰般的新增了許多功能及特色,其中又以支援開發Windows 7作業系統中的多點觸控(Multitouch)及Ribbon華麗使用者介面更令人激賞,程式開發者只要透過MFC高度封裝好的類別,就可以簡單的上手進行新世代應用程式之開發,不得不讓目前業界許多還在使用Visual C++ 6.0的程式開發人員有非常大的動力想要投入新開發工具的懷抱中。


結語
隨著Visual Studio 2010的到來,平行運算的開發模式將會越來越普及,在過去開發人員著重的是如何精簡程式碼、減少記憶體的耗用度,而現在除了過去的思維之外,開發人員應該更要思考:系統架構要如何設計才能更符合平行運算,甚至是時下非常熱門的雲端計算架構,透過學習新的技術來提昇自己的價值,建置出更強大而且更有效率的系統。