最近在學一門課,叫作「C++與並行計算」。要用到多CPU(進程)並行的原理,實現語言是C++的MPI接口。聯想到上學期用到CUDA C/C++來作並行計算,就對這兩門語言作一個總結,分享下本身關於並行計算的認識。php
並行計算通常有兩個維度,一個是指令(Instruction)或程序(Program),另外一個是數據(Data)。這樣,就能夠概括出各類並行模式(S表明Single,M表明Multiple)。程序員
除了SISD,其餘幾個都算是並行計算方法。這裏重點介紹下SPMD。編程
SPMD是最簡單的一種並行計算模式。SP意味着程序員只需寫一份代碼,MD意味着這些代碼對不一樣的數據應該分別處理。而並行,則要求數據處理的過程要同時進行。通俗的講,就是一份代碼被複制了多份,而後每份代碼單獨跑一份數據,從而實現並行。這就引出了一個問題:數據是如何存儲的?架構
數據的存儲能夠分爲兩大類:分佈式存儲和共享內存。框架
分佈式存儲意味着不一樣的進程/指令處理不一樣的數據,你們互相不干擾。基於多CPU的MPI並行計算接口用的就是這種思想。機器學習
共享內存則要求不一樣的進程/指令能夠同時修改同一塊數據。這樣,進程之間的通訊將變得簡單。缺點是容易形成數據讀寫衝突而須要謹慎對待。基於GPU的CUDA C/C++並行計算就用到了這種方法。分佈式
鑑於最近幾年我的計算機多CPU的興起,利用多個CPU來處理同一個任務不失爲最簡單的並行計算方法。其中的表明方法就是MPI。MPI全稱是Message Passing Interface,是一個消息傳遞接口(或約定)。MPI的特色能夠用如下幾點來歸納:學習
1. MPI屬於SPMD框架;大數據
2. 數據是分佈式存儲的;優化
3. 把握進程之間消息的傳遞是寫好MPI程序的關鍵!
最簡單的MPI 「Hello, World!」程序以下:(存儲爲hello.c)
#include <stdio.h> #include <mpi.h> // MPI庫 int main(int argc, char *argv[]) { MPI_Init(&argc, &argv); // 啓動MPI並行計算 printf("Hello, World!\n"); MPI_Finalize(); // 結束MPI並行計算 return(0); }
MPI程序的編譯不一樣於通常的C/C++程序,須要用單獨的mpi命令編譯。對於C MPI程序,編譯命令是mpicc;對於C++ MPI程序,編譯命令則是mpigxx。例如編譯上面的C MPI程序:
$mpicc hello.c -o hello
一樣,運行C/C++ MPI程序須要用到mpi的運行命令:mpirun 或 mpiexec。最經常使用的格式以下:
$mpirun -np 3 hello
-np是可選的參數,表示啓動的進程數,默認爲1。這裏啓動了三個進程,從而屏幕上將打印出三行"Hello, World!"。
GPU並行計算的崛起得益於大數據時代的到來,而傳統的多CPU並行計算已經遠遠不能知足大數據的需求。GPU最大的特色是它擁有超多計算核心,每每成千上萬核。而每一個核心均可以模擬一個CPU的計算功能,雖然單個GPU核心的計算能力通常低於CPU。
CUDA,全稱是Compute Unified Device Architecture,即統一計算架構,是由生產GPU最有名的英偉達公司提出的CPU+GPU混合編程框架。CUDA C/C++語言有以下特色:
1. 也是SPMD框架;
2. 兼有分佈式存儲和共享內存的優勢;
3. 把握GPU的帶寬是充分利用GPU計算資源的關鍵。
通常,通過必定優化的CUDA C/C++程序的計算速度相比於傳統的CPU程序的計算速度要快幾倍到幾十倍。正由於如此,在目前火熱的深度學習領域,愈來愈多的科研工做者和工程師都開始利用GPU和CUDA來並行加速。
並行計算,尤爲是利用GPU和CUDA來並行加速是很誘人的一門技術。然而,從我我的的經驗來說,寫一個並行計算程序比寫一個串行程序難多了。難點主要體如今如下幾點:
1. 並行程序須要更長的代碼,從而增長了工做量;
2. 並行程序的各個進程執行進度不肯定,增長了debug的困難。
3. 須要對硬件架構、內存有更高的把握。
不過,考慮到並行計算誘人的前景,這些難點仍是值得克服的。至少,對於一個機器學習的科研工做者而言,幾十倍的速度將大大的減小用於作實驗的時間。因此,何樂而不爲呢?
歡迎討論!
參考:
1. SPMD:http://en.wikipedia.org/wiki/SPMD
2. MPI:https://www.sharcnet.ca/help/index.php/Getting_Started_with_MPI