lesson1
- 多核的概念
單芯片多處理器,簡稱CMP
例題:
爲什麼說從單核到多核的轉變成爲不可避免的歷史趨勢:(D)
A. 指令級並行的侷限
B. 能耗與散熱
C. 內存牆問題
D. 以上都是 - 弗林分類(縮寫也要記住):
單指令流單數據流(SISD)
單指令流多數據流(SIMD)
多指令流單數據流(MISD)
多指令流多數據流(MIMD)
例題:
陣列處理機又稱爲並行處理機,它的體系結構屬於_______計算機。(B)
A.SISD
B.SIMD
C.MIMD
D.MISD
弗林(Flynn )根據指令流和數據流的不同組織方式,把計算機系統的結構進行了分類,以下屬於弗林分類的是:(ABCD )
A. 單指令流單數據流(Single Instruction stream Single Data stream – SISD)
B. 單指令流多數據流(Single Instruction stream Multiple Data stream – SIMD)
C. 多指令流單數據流(Multiple Instruction stream Single Data stream – MISD )
D. 多指令流多數據流(Multiple Instruction stream Multiple Data stream – MISD )
以下哪個不屬於SIMD。(D)
A. 並行處理機
B. 陣列處理機
C. 向量處理機
D. 標量流水線處理機 - 進程與線程的區別、線程狀態
進程擁有獨立的地址空間,而線程和其他線程共享進程的地址空間。
進程之間的通信可以使用操作系統原語或通過共享存儲空間來實現,而線程使用當前程序設計語言的原語或者通過進程共享空間來實現通信。
進程上下文的切換是重量級的,進程所有狀態都要保存。而線程之間的切換是輕量級的,只需要保存當前寄存器的狀態
例題:
什麼是線程、進程,它們之間的關係是什麼?
答:進程是一組離散的(執行)程序任務集合;線程是進程上下文中執行的代碼序列,又被稱爲輕量級進程。進程中可包含一個或多個線程。
對於進程,以下表述不正確的是:(D )
A. 進程是指程序在一個數據集合上運行的過程
B. 進程是系統進行資源分配和調度運行的一個獨立單位
C. 在操作系統中引入進程的目的,是爲了使多個程序併發執行,以改善資源利用率及提高系統的吞吐量
D. 在操作系統中引入進程的目的,是爲了減少程序併發執行時所付出的時空開銷,使操作系統具有更好的併發性
對於線程,以下表述不正確的是:( C )
A. 線程是進程中的一個實體,是被系統調度和分配的基本單元
B. 每個程序至少包含一個線程,那就是主線程
C. 線程自己只擁有很少的系統資源,且不可與同屬一個進程的其他線程共享所屬進程所擁有的全部資源
D. 同一進程中的多個線程之間可以併發執行,從而更好地改善了系統資源的利用率
以下表述不正確的是:( C )
A. 人們習慣上稱線程爲輕量級進程(lightweight process, LWP ),線程是CPU 調度和分派的基本單元
B. 在創建或撤消進程時,系統都要爲之分配或回收資源
C. 進程切換的開銷也遠小於線程切換的開銷
D. 線程切換隻需保存和設置少量寄存器的內容,並不涉及存儲器管理方面的操作
在操作系統中引入進程的目的是:(A )
A. 提高系統吞吐量
B. 減少程序併發執行時所付出的時空開銷
C. 便於組織程序邏輯
D. 以上都正確
在操作系統中引入線程的目的是:(B )
A. 提高系統吞吐量
B. 減少程序併發執行時所付出的時空開銷
C. 便於組織程序邏輯
D. 以上都正確
______是CPU 調度和分派的基本單位,______是資源擁有的基本單位。(D)
A. 線程,線程
B. 進程,線程
C. 進程,進程
D. 線程,進程 - 進程狀態及其轉換
例題:
對於線程生命週期,以下表述正確的是:(D )
A. 系統中的每個線程都有一個從創建到消亡的過程,我們把這一過程稱作該線程的生命週期。
B. 線程生命週期包括創建、就緒狀態、運行狀態、等待狀態和消亡
C. 就緒狀態的線程運行所需的一切條件都得到滿足,已獲得必要的資源和設備。但因處理器資源個數少於線程個數,所以該線程不能運行,而必須位於隊列中等待分配處理器資源
D. 以上都正確 - 片上多核處理器(單芯片多處理器)
片上多核處理器(Chip Multi-Processor,CMP)就是將多個計算內核集成在一個處理器芯片中,從而提高計算能力。 - 計算機硬件工藝發展順序
電子管數字計算機、晶體管數字計算機、集成電路數字計算機、大規模集成電路數字計算機
全世界第一臺全自動電子數字計算機ENIAC 於哪一年研製成功?(B )
A.1944 年
B.1945 年
C.1946 年
D.1947 年
計算機的硬件工藝發展順序是:(A )
A. 電子管數字計算機、晶體管數字計算機、集成電路數字計算機、大規模集成電路數字計算機
B.晶體管數字計算機、電子管數字計算機、集成電路數字計算機、大規模集成電路數字計算機
C.電子管數字計算機、集成電路數字計算機、大規模集成電路數字計算機、晶體管數字計算機
D. 電子管數字計算機、集成電路數字計算機、晶體管數字計算機、大規模集成電路數字計算機
lesson2
- 多核多線程開發流程
其中,第三步確定分解模式有:分任務、分數據、分數據流
第五步選擇並行模型有:Win32,OpenMP,MPI,TBB - 分解模式
任務分解、數據分解、數據流分解
數據分解:減少數據的關聯性 接觸面積小點 (ppt第九頁) - 處理數據依賴的方法
變量本地化(減少數據關聯),改造變量,規約(前提:切片),明確的同步機制
lesson3
- 句柄
句柄是一種指向指針的特殊指針。Windows中的句柄實際上是一個唯一的數字,它引用一個Windows對象,例如窗口、圖標等。
Windows內存管理器在移動對象在內存中的位置後,把對象新的地址告知句柄地址來保存。這樣只需記住句柄地址就可以間接知道對象具體在內存中的哪個位置。
句柄地址(穩定)→記載着對象在內存中的地址→對象在內存中的地址(不穩定)→實際對象
下面哪個說法是正確的(AB )
A. 每個進程被初始化時,系統爲它分配一個句柄表,用於保存該進程使用的內核對象信息
B. 相同的句柄值在不同的進程中可能標識不同的內核對象
C. 一個進程中止執行,它使用的內核對象也會被撤銷
D. 內核對象是由進程擁有的 - 線程執行函數
記住函數頭 - 創建線程、等待線程、等待多個線程、撤銷線程等四個函數,涉及到的所有程序
創建線程:CreateThread(NULL,0,helloFunc,NULL,0,NULL);
等待一個線程:WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);
如:WaitForSingleObject(hThread , INFINITE);
等待多個線程:WaitForMultipleObjects(numThreads, hThread,TRUE, INFINITE);
線程退出:BOOL CloseHandle(HANDLE hObject);
例題:
簡述下列Windows多線程程序設計中常用函數的含義
答案就是上邊的那個
分析以下程序可能出現的結果及原因
結果:#include <stdio.h> #include <windows.h> DWORD WINAPI helloFunc(LPVOID arg ) { printf(“Created thread says ‘Hello’ \n”); return 0; } void main( ) { HANDLE hThread = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL ); printf(“Main thread says ‘Hello’ \n”); CloseHandle(hThread); }
(1)Main thread says ‘Hello’
Created thread says ‘Hello’
(2)Created thread says ‘Hello’
Main thread says ‘Hello’
(3)Main thread says ‘Hello’
情況三是主線程執行完之後就直接觸發CloseHandle(hThread)方法
期望的結果是情況二,如果想弄成這樣的話,可以使用全局變量+輪循(ppt 14)或者WaitForSingleObject
可能出現const int numThreads = 4; DWORD WINAPI threadFunc(LPVOID pArg) { int* p = (int*)pArg; int myNum = *p; printf("Thread number %d\n", myNum); return 0; } void main() { HANDLE hThread[numThreads]; for (int i = 0; i < numThreads; i++) { hThread[i] = CreateThread(NULL, 0, threadFunc, &i, 0, NULL); } WaitForMultipleObjects(numThreads, hThread, TRUE, INFINITE); }
4444
0123等
出現這種結果是因爲四個線程共享i,產生數據競爭,既讀又寫
解決方法:變量本地化(ppt 24) - win32線程同步的實現方法
全局變量、事件、互斥量、臨界區、信號量
前兩個處理先後順序(同步)問題,後三個處理互斥問題,其中事件是專門處理先後順序的,互斥量也可處理先後順序 - 賣票的
#include <windows.h> #include <iostream.h> DWORD WINAPI Fun1Proc(LPVOID lpParameter); DWORD WINAPI Fun2Proc(LPVOID lpParameter); int tickets=100; HANDLE hMutex;/// void main() { hMutex=CreateMutex(NULL,FALSE,NULL);/// HANDLE hThread1; HANDLE hThread2; hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL); hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL); HANDLE hThreads[2] = {hThread1, hThread2}; WaitForMultipleObjects(2,hThreads,TRUE,INFINITE); CloseHandle(hThread1); CloseHandle(hThread2); CloseHandle(hMutex);/// } DWORD WINAPI Fun1Proc(LPVOID lpParameter) { while(TRUE) { WaitForSingleObject(hMutex,INFINITE);/// if(tickets>0) { Sleep(2); cout<<"thread1 sell ticket : "<<tickets--<<endl; } else break; ReleaseMutex(hMutex);/// } return 0; } DWORD WINAPI Fun2Proc(LPVOID lpParameter) { while(TRUE) { WaitForSingleObject(hMutex,INFINITE);/// if(tickets>0) { Sleep(2); cout<<"thread2 sell ticket : "<<tickets--<<endl; } else break; ReleaseMutex(hMutex);/// } return 0; }
lesson4
-
OpenMp特徵
一種面向共享內存以及分佈式共享內存的多處理器多線程並行編程語言。
執行模型採用Fork-Join的形式
以下表述錯誤的是:(D)
A. OpenMP 可以根據目標系統儘量使用最優數量的線程個數
B. 使用線程池可以避免爲每個線程創建新進程的開銷
C. 線程池通常具有最大線程數限制,如果所有線程都繁忙,而額外的任務將放入隊列中,直到有線程可用時才能夠得到處理
D.對於有優先級的線程,也可以使用線程池
以下表述不正確的是:(D )
A. OpenMP 的編程模型以線程爲基礎,通過編譯製導語句來顯示地制導並行化,爲編程人員提供了對並行化的完整控制
B. OpenMP 的執行模型採用Fork-Join 的形式
C. Fork-Join 執行模式在開始執行的時候,只有一個叫做主線程的運行線程存在
D. OpenMP 同時支持C/C++語言和Java 語言 -
“helloworld”中涉及到的函數
#include “omp.h” int main ( ){ printf(“Hello from serial.\n”); //串行執行 printf(“Thread number = %d\n”, omp_get_thread_num( )); omp_set_num_threads(4); #pragma omp parallel //開始並行執行 { printf(“Hello from parallel. Thread number=%d\n”,omp_get_thread_num( )); }//沒有,默認並行距離最近的語句結構 printf(“Hello from serial again.\n”); return 0; }
-
求PI的程序
OpenMP
#include "stdafx.h" #include <omp.h> #include <time.h> long num_steps = 100000000; double step; int main(){ clock_t start, stop; double x,pi,sum=0.0; int i; step = 1.0 /(double) num_steps; start=clock(); omp_set_num_threads(4); #pragma omp parallel for private(x) reduction( +:sum) for(i=0;i<num_steps; i++){ x=(i+0.5)*step; sum = sum+4.0/(1.0+x*x); } pi = sum*step; stop= clock(); printf( "The value of PI is %15. 12f\n",pi); printf("The time to calculate PI was %f seconds\n", ((double)(stop-start)/1000.0)); return 0: }
-
子句的掌握:parallel for reduction private barrier
parallel 後續語句按多線程方式運行
parallel for 後續的for循環語句按多線程方式運行
parallel private 並行區變量私有化指導語句,說明後續語句中的某變量在多線程方式運行時被各線程私有化,每次僅容許一個線程訪問的變量
parallel reduction
如:#pragma omp parallel for private(x) reduction(+:sum)
每個線程運行都得到一個sum,所有線程都執行完後再把所得的所有sum加起來
parallel barrier 用於並行區內代碼的線程同步,所有線程執行到 barrier 時要停止,直到所有線程都執行到 barrier 時才繼續往下執行。 -
任務調度的方法
靜態調度 static
動態調度 dynamic
guided調度
runtime調度
以下哪些不是OpenMP 的負載平衡調度方案:(D )
A.static
B.dynamic
C.runtime
D.public -
程序性能分析實例
高精度性能計數器:QueryPerformanceFrequency( (LARGE_INTEGER*)&frequency); QueryPerformanceCounter( (LARGE_INTEGER*)&counter);
lesson6
- 非阻塞(CAS)算法的特徵
無阻塞 只要沒有競爭,線程就可以持續執行
無鎖 系統整體持續執行
無等待 每個線程都可以持續執行,即使遇到競爭 - 線程安全函數
一個線程安全的函數通過加鎖的方式來實現多線程對共享數據的安全訪問。
非可重入函數可能無法滿足線程安全要求,不可用於多線程環境。
線程函數安全化:
爲共享資源加鎖
對於非線程安全函數:
(1) 使用作用於整個函數庫的鎖
(2) 使用作用於單個庫組件/一組組件的鎖 - 數據競爭是指在多線程程序中,不同線程對共享變量的訪問沒有特定的順序,發生讀寫操作和寫寫操作。
lesson7
- MPI 特徵:
MPI是一種消息傳遞編程模型,併成爲這種編程模型的代表和事實上的標準。消息傳遞方式是廣泛應用於多類並行機的一種模式,特別是分佈存儲並行機(分佈式系統)。 - 6個接口函數概念和4個組通信接口概念
6個接口函數
(1)初始化:int MPI_Init(int *argc, char ***argv)
MPI程序的第一個調用,完成MPI程序所有的初始化工作,將命令行參數傳給各個進程。
(2)獲取當前進程標識
int MPI_Comm_rank(MPI_Comm comm,int *rank)
函數返回時,rank中存放當前進程在給定的通信域中的進程標識號。
(3)獲取通信域包含的進程數
int MPI_Comm_size(MPI_Comm comm,int *size)
函數返回時,size中存放指定通信域中的進程數。
(4)消息發送
源進程將緩存中的數據發送到目的進程。
int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag,MPI_Comm comm)
(5)MPI_Recv
接收源進程source的消息,並且該消息的數據類型和消息標識和本API指定的datatype和tag相一致。
接收到的消息所包含的數據元素的個數最多不能超過count個。若超過count個,則會發生溢出錯誤。若少於count個,則只有相應於這個消息的那些地址上的內容被修改。
count可以是0,這種情況下的數據部分是空的
(6)MPI程序的結束
int MPI_ Finalize()
MPI程序的最後一個調用,結束MPI程序的運行。它是MPI程序的最後一條可執行語句,否則程序的運行結果是不可預知的。
四個通信接口
(1)廣播 一個任務給多個進程
根進程將一條消息發送到組內的所有其它進程,同時也包括它本身在內。
Int MPI_Bcast(void *buffer, int count, MPI_Datatype datatype, int root,MPI_Comm comm)
(2)散發 分片
根進程將數據的不同部分分別發送給各個進程。
Int MPI_Scatter(void *sendbuf, int sendcount, MPI_Datatype data, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
(3)收集
每個進程將自身發送緩衝區中的消息發送到根進程,根進程依據發送進程的進程標識號將它們各自的消息依次存放到自己的消息緩衝區中。
Int MPI_Gather(void *sendbuf, int sendcount, MPI_Datatype data, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm)
(4)歸約 收集時做的操作
將每個進程緩衝區中的數據按給定的操作進行運算,並將計算結果返回到根進程的輸出緩衝區中。
Int MPI_Reduce(void *sendbuf, void *recvbuf, int count, MPI_Datatype data,MPI_Op op, int root, MPI_Comm comm)
lesson8
- TBB的特徵:是C++的擴展庫
補充
- Flynn將計算機劃分爲四種基本類型,即SISD,SIMD,MISD,MIMD。
- 線程的狀態分爲就緒、阻塞和運行狀態。
- 一組進程(線程)中的每個進程(線程)均等待此組進程(線程)中某一其它進程(線程) 所佔有的,因而永遠無法得到的資源,這種現象稱作死鎖。
- 分解足將應用程序劃分成多個獨立的任務,並確定這些任務之間的相互關係的過程,分解方 式包括數據分解、任務分解和數據流分解。
- 片上多核處理器的英文縮寫是CMP。
- 獨立於體系結構性能優化方法主要有:避免冗餘的函數調用、避免不必要的邊界檢查和變量本地化。
講解音頻:鏈接: https://pan.baidu.com/s/1qmKvw0QoG465zGi6_d3zOg 提取碼: 9ax3
PPT及相關複習資料:冰炫上有