Top Banner
認認 C++11 認認認認認 認 AMP 認認認認認認認認 Dev306 王王王 qing.chwang at gmail.com
100

認識 C++11 新標準及使用 AMP 函式庫作平行運算

Jun 09, 2015

Download

Technology

C++新標準 - C++11
使用C++ AMP做平行運算
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

認識 C++11 新標準及使用 AMP 函式庫作平行運算

Dev306

王建興qing.chwang at gmail.com

Page 2: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

講者簡介現職

聖藍科技技術長興趣

網路應用系統開發譯作

Thinking in Java 4th Edition, 正體中文版Thinking in Java 2nd Edition, 正體中文版Essential C++, 正體中文版

專欄iTHome 電腦報程式人專欄

連絡方式: qing at gmail.com

Page 3: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Agenda

C++ 新標準 - C++11使用 C++ AMP 做平行運算

Page 4: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++ 新標準- C++11

Page 5: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++11

C++11 ,先前被稱作 C++0x ,即 ISO/IEC 14882:2011C++11 ,是目前的 C++ 程式語言的正式標準

取代第二版標準 ISO/IEC 14882:2003在 2011 年八月正式成為標準,故名為 C++11

Page 6: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++11 要達成的目標

讓 C++ 成為在系統程式設計以及程式庫設計領域中較好的程式語言

直接使用 C++ 而非為特定應用領域提供專門的開發語言

使 C++ 更易於教導及學習增加一致性、加強安全性、為初學者提供相關的機制

如何達成在維持效能甚至提升效能的同時,提供更高階、更抽象化

*http://www.stroustrup.com/C++11FAQ.html#aims

Page 7: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++ 11 中的增進 – Core Language

執行時期的效能增進,例如:rvalue reference對 POD 定義的修改

建構時期的效能增進,例如:extern template

使用性的加強,例如:型別的推論Range-based for-loop

功能的改進,例如static assertion

Page 8: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++ 11 -從 VC10 到 VC11 (1/3)

http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx

Page 9: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++ 11 -從 VC10 到 VC11 (2/3)

Page 10: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++ 11 -從 VC10 到 VC11 (3/3)

Page 11: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Concurrency – 從 VC10 到 VC11

Page 12: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

今天要談的 C++11 特色 (1/2)

Right angle bracketsextern templateenum ClassPOD 定義的修改區域及不具名的型別做為模版的參數Range-for 述句

Page 13: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

今天要談的 C++11 特色 (2/2)

auto Keyworddecltype Type SpecifierLambda Expressionsrvalue referencesstatic_assertnullptr

Page 14: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Right Angle Brackets

在 C++98 中,這是語法錯誤的寫法編譯器會將 >> 認為是運算子 >>新編譯器將能理解此種語法

list<vector<string>> lvs;

Page 15: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

extern template

避免多重實例化模版,明確指定模版於它處實例化編譯器毋需重複實例化,待鏈結時期再尋找實例化後的程式碼即可

#include "MyVector.h"extern template class MyVector<int>; // Suppresses implicit instantiation below --

// MyVector<int> will be explicitly instantiated elsewherevoid foo(MyVector<int>& v){ // use the vector in here}

-------------------------------------------

#include "MyVector.h"template class MyVector<int>; // Make MyVector available to clients (e.g., of the shared library

*http://www.stroustrup.com/C++11FAQ.html#extern-templates

*http://zevoid.blogspot.tw/2012/04/c11-extern-template.html

Page 16: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

傳統 C++ 在 enum 上的問題

傳統的 enum 在轉型時會被自動視為 int ,不符合此規則時則會引發錯誤傳統的 enum 其列舉值在其外圍的程式碼範圍內皆為可見,這易於產生名稱上的衝突無法指定 enum 的底層型別,容易造成誤解以及相容性的問題無法進行先行宣告

http://www.stroustrup.com/C++11FAQ.html#enum

Page 17: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

enum class (更高階的 enum )

Scoped and Strongly typed enumsVC10 中並未支援, VC11 已支援

enum Alert { green, yellow, election, red };

enum class Color { red, blue };

enum class TrafficLight { red, yellow, green };

Alert a = 7;Color c = 7; int a2 = red; int a3 = Alert::red; int a4 = blue; int a5 = Color::blue; Color a6 = Color::blue;

Error Error in C++98; OK in C++11

Page 18: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

指定 enum 的底層型別

enum class Color : char { red, blue };

enum class TrafficLight { red, yellow, green };

enum E { E1 = 1, E2 = 2, Ebig = 0xFFFFFFF0U }; // how big is an E?

enum EE : unsigned long { EE1 = 1, EE2 = 2, EEbig = 0xFFFFFFF0U };

並同時決定 enum 的佔用空間在過去,佔用空間取決於實作而定底層型別必須是整數型的型別,預設為 int

Page 19: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

enum 的先行宣告

enum class Color_code : char; void foobar(Color_code* p);// ...enum class Color_code : char { red, yellow, green, blue };

C++11 中可以做先行宣告了

Page 20: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

enum Class 的意義

讓列舉型別的表示方式更高階、更抽象、更直覺即使是 C++ 的後繼者 Java ,一開始也沒有專門的 enum type ,而是在 J2SE 5.0之後加入

Page 21: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

對 POD 定義的修改

POD ( Plain Old Data )符合這種定義的型別能夠允許產生與 C 相容的物件佈局 在 C++98 , POD 指的是像 C 中 struct那樣的資料

能使用 memcpy()能使用 memset() 進行初始化

struct S { int a; }; // S is a PODstruct SS { int a; SS(int aa) : a(aa) { } }; // SS is not a PODstruct SSS { virtual void f(); /* ... */ };

Page 22: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++11 中的 POD

在 C++11 中, SS也是個 POD建構式並不影響

SSS 不會是 POD ,因為會有個虛擬函式表C++ 定義 POD 是可複製的型別、極簡型別、以及具有標準佈局的型別VC10 中並未支援, VC11 已支援

struct S { int a; }; // S is a PODstruct SS { int a; SS(int aa) : a(aa) { } }; // SS is a PODstruct SSS { virtual void f(); /* ... */ };

Page 23: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

極簡( trivial )型別或結構

極簡的預設建構式。這可以使用預設建構式語法

例如 SomeConstructor() = default;極簡的複製建構式,可使用預設語法極簡的賦值運算子,可使用預設語法極簡的解構式,不可以是虛擬的

*http://zh.wikipedia.org/zh-tw/C%2B%2B11

Page 24: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

標準佈局 (standard-layout) 的型別或結構 只有非靜態的資料成員,且這些成員也是符

合標準佈局的型別對所有非靜態成員有相同的存取控制沒有虛擬函式,也沒有虛擬基礎類別只有符合標準佈局的基礎類別沒有和第一個定義的非靜態成員相同型別的基礎類別若非沒有帶有非靜態成員的基礎類別,就是最底層 (繼承最末位 ) 的型別沒有非靜態資料成員而且至多一個帶有非靜態成員的基礎類別。基本上,在該型別的繼承體系中只會有一個型別帶有非靜態成員

Page 25: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

POD 的標準

Class/struct/union 被視為是 POD 要滿足三個條件

它是極簡的型別或結構它是標準佈局的型別或結構其所有資料成員及基礎類別皆為 PODs

Page 26: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

區域及不具名的型別做為模版的參數

在 C++98 ,區域及不具名的型別不能做為模版的參數傳入如今,在 C++11 中支援了

一致性更好void f(vector<X>& v){

struct Less {bool operator()(const X& a, const X& b){ return a.v<b.v; }

};sort(v.begin(), v.end(), Less()); // C++98: error: Less is local

// C++11: ok}

*http://www.stroustrup.com/C++11FAQ.html#local-types

Page 27: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

不具名型別的值也能做為模版參數

template<typename T> void foo(T const& t){}enum X { x };enum { y };

int main(){

foo(x); // C++98: ok; C++11: okfoo(y); // C++98: error; C++11: okenum Z { z };foo(z); // C++98: error; C++11: ok

}

Page 28: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

auto Keyword (1/3)

auto 關鍵字能從所宣告變數的初始算式,導出其型別 ( 當然是編譯時期 )

auto declarator initializer;

int j = 0; auto k = 0; // Variable k is implicitly type int

*http://msdn.microsoft.com/en-us/library/dd293667(v=VS.100).aspx

Page 29: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

auto Keyword (2/3)

map<int,list<string>>::iterator i = m.begin(); auto i = m.begin();

auto x = 1, *y = &x, **z = &y; // Resolves to int. auto a(2.01), *b (&a); // Resolves to double. auto c = 'a', *d(&c); // Resolves to char. auto m = 1, &n = m; // Resolves to int.

Page 30: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

auto Keyword (3/3)

使用 auto 關鍵字時的重要限制使用時一定要搭配 initializer不能用來宣告陣列、變數的 return type 、函式或 template 的參數 除了 static member 之外,不能在 class/struct 中使用 auto 宣告 data member

Page 31: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

錯誤的 auto 使用

auto a;auto ary[10];auto ary2[] = { 1, 2, 3}auto foo();void bar(auto a);struct A{ auto a;};

Page 32: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

使用 auto 的時機

當資料型別可能隨著編譯器或目標平台而異時

例 strlen() 的回傳型別當資料型別過於複雜不易表示時

例 map<int,list<string>>::iterator i 將 Lambdas 指派至變數時 ( 待續 , Lambdas 算式 )指定 Trailing Return Types ( 待續 , decltype )

Page 33: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

auto vs. auto

/Zc:auto[-] 編譯器選項是用來告訴編譯器看待宣告變數時 auto 這個關鍵字的確切意義指定 /Zc:auto 編譯器會從所宣告變數的初始算式推導出其確型別指定 /Zc:auto- 編譯器會以 automatic storage class 來宣告變數此為相容性問題

*http://msdn.microsoft.com/en-us/library/dd293615.aspx

Page 34: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

decltype Type Specifier (1/2)

decltype 是個 type specifierdecltype 依據所給定的算式來決定型別

decltype 不同於 typeid ,因為它是從算式中得到型別本身,而非型別資訊

decltype( expression )

Page 35: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

decltype Type Specifier (2/2)

int var; const int&& fx(); struct A { double x; }const A* a = new A();

decltype(fx()); // const int &&decltype(var) // intdecltype(a->x) // double ( The type of the member access )decltype((a->x)) // const double && (an expression instead of a member access )

Page 36: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

使用 decltype 的時機

適當的表示資料型別

decltype 和 auto 不同的是, auto 推導型別是靠初始算式,得發生指派動作decltype 只是從算式評估結果的型別來推導型別,但卻不會確切的進行評估

decltype(mstr.begin()->second.get_allocator()) under_alloc;

decltype(mstr.begin()->second.get_allocator()) under_alloc;

Page 37: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

trailing-return-type

auto function_name( parameters ) −> decltype( expression ){ function_body;}

template<typename T, typename U>auto myFunc( T& t, U& u)-> decltype( t + u ){ return t + u;};

Page 38: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++11 對型別推論的加強

auto 及 decltype 其作用皆是在編譯時期推論型別編譯器在編譯時期確切的能從變數的初始化述句以及算式得到最終該有的型別編譯時期的動作不影響執行時期的效能

C++ 的一貫哲學之所以要有型別推論不是因為那些顯而易見的型別宣告問題

長久以來 C++ 程式設計者受模版庫中複雜的型別宣告所苦 它們確切究竟是什麼型別並不那麼重要

Page 39: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Ranged-for透過 Ranged-for 述句,可以在迴圈裡遞代一組元素所有標準的容器、 std::string 、初始化列表、陣列、以及所有可以定義 begin() 及end() 的類別都可適用void f(vector<double>& v){

for (auto x : v) cout << x << '\n';for (auto& x : v) ++x;

}

*http://www.stroustrup.com/C++11FAQ.html#aims

for (const auto x : { 1,2,3,5,8,13,21,34 }) cout << x << '\n';

Page 40: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Ranged-for 的意義

提供更高階的迴圈語義Compiler Sugar即使如 Java ,也在 J2SE 5.0之後,加入了forech 的語法

Page 41: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Lambda Expressions(1/4)

基本上就像是個匿名函式( anonymous function )

Lambda Expression 使得函式可以在使用的地方定義,並且可以在 Lambda 函式中使用 Lambda 函式之外的變數比函式物件或函式指標方便且單純

[]() mutable throw() -> typeid{ //function body}

Page 42: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Lambda Expressions(2/4)

1.capture clause 2.parameter list 3.mutable specification 4.exception specification5.return type6.lambda body

Page 43: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Lambda Expressions (3/4)capture clause

*http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!10575.entry

Page 44: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Lambda Expressions (4/4)parameter list

不能有預設引數不能有可變長度引數列表不能有不具名參數沒有參數時,可省略 parameter list

int main(){ int x = 4; int y = 5; int z = [=] { return x + y; } ;}

Page 45: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

使用函式物件

struct FunctionObj { void operator()(int n) const {

// 對 n 操作 }}…for_each(v.begin(), v.end(), FunctionObj ());

Page 46: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

使用 Lambda Expression

for_each(v.begin(), v.end(), [] (int n) {// 操作 n

}

Page 47: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

rvalue references

rvalue reference 被創造,其中最大的意義之一,便是為了提供更有效率的 move 語義rvalue reference 語法type-id && cast-expression

*http://msdn.microsoft.com/en-us/library/dd293668(v=VS.100).aspx

Page 48: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

lvalue & rvalue (1/2)

每個算式,若非 lvalue 便為 rvaluelvalue 指的是在單一算式之後所代表的一個續存物件

例: ++xrvalue 指的是在算式評估結束之後,生命期便結束的暫時性物件

例: x++能對它取址的即為 lvalue

*http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx

Page 49: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

lvalue & rvalue (2/2)

string one("cute");const string two("fluffy");string three() { return "kittens"; }const string four() { return "are an essential part of a healthy diet"; }

one; // modifiable lvaluetwo; // const lvaluethree(); // modifiable rvaluefour(); // const rvalue

Page 50: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++ 的複製問題

每次 + 運算子執行時,都會產生一個暫時性物件

string s0("my mother told me that");string s1("cute");string s2("fluffy");string s3("kittens");string s4("are an essential part of a healthy diet");

string dest = s0 + " " + s1 + " " + s2 + " " + s3 + " " + s4;

產生了八個暫時性物件!

Page 51: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

問題出在那裡?

因為 s0 是個 lvalue 不能加以修改,所以在計算 s0 + “ “ 時,得建立一暫時物件但在接著計算 (s0 + “ ”) + s1 時,可以直接把 s1 接到之前建立的暫時物件後,便毋需再產生第二個暫時物件,並捨棄第一個暫時物件這便是 move 語義的核心觀念

Page 52: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

move 語義的實作 (1/2)

在 C++11 中,每次 + 運算子被呼叫時,仍會產生獨立的暫時物件但第二次呼叫 + 運算子時(例如在( (s0 + “ ”) + s1 )中),會將前一個暫時物件所配置的記憶體挪過來使用只更動第二個暫時物件指標之值,而不重新配置並複製第一個暫時物件的指標則指向 null ,避免解構時的相關行為

Page 53: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

move 語義的實作 (2/2)

所以,若能偵測到處理的是 non-const rvalue 時,就可以直接挪用其記憶體反正它很快就要被摧毀,又沒人在乎它

從 rvalue 建立物件,或指派 rvalue 物件之值至另一物件時,所謂的 moving ,便是挪用其記憶體的動作例如 vector 要擴展空間時, moving 就很重要那問題就是在於要如何偵測了!

Page 54: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

rvalue reference

C++11 引入了名為 rvalue reference 的新 reference ,其語法為 Type&&  及 const Type&& rvalue reference 與 lvalue reference 是不同的型別但在語意上都一樣是 reference

Page 55: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

兩種 reference 在函式重載時的不同行為

Type& 只能繫結到 non-const lvalue const Type&  可以繫結到任何東西Type&&  可以繫結到 non-const lvalue 及 non-const rvalue const Type&&  可以繫結到任何東西

Page 56: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

rvalue reference 的 overload resolution

void purr(const string& s) { cout << "purr(const string&): " << s << endl;}void purr(string&& s) { cout << "purr(string&&): " << s << endl;}string strange() { return "strange()";}const string charm() { return "charm()";}

int main() { string up("up"); const string down("down");

purr(up); // purr(const string&): up purr(down); // purr(const string&): down purr(strange()); // purr(string&&): strange() purr(charm()); // purr(const string&): charm()}

Page 57: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

提供 move 語義

傳統的 copy 建構子

C++0x 中的 move 建構子

編譯器並不會提供預設的 move 建構子

Simple(const Simple&);

Simple(Simple&&);

* 範例取自 http://www.codeproject.com/KB/cpp/cpp10.aspx#RValues

Page 58: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

move 建構子被呼叫

Simple GetSimple(){ Simple sObj(10); return sObj;}

Page 59: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

實作 move 建構子 (1/2)class Simple{ // The resource void* Memory;

public: Simple() { Memory = nullptr; }

// The MOVE-CONSTRUCTOR Simple(Simple&& sObj) { // Take ownership Memory = sObj.Memory; // Detach ownership sObj.Memory = nullptr; }};

Page 60: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

實作 move 建構子 (2/2)

Simple(int nBytes) { Memory = new char[nBytes]; }

~Simple() { if(Memory != nullptr) delete []Memory; }};

Page 61: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

move 指派運算子

傳統的 copy 指派運算子

C++0x 中的 move 指派運算子void operator=(const Simple&);

void operator=(Simple&&);

Page 62: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

實作 move 指派運算子

class Simple{ ... void operator = (Simple&& sOther) { // De-allocate current delete[] Memory;

// Take other's memory contnent Memory = sOther.Memory;

// Since we have taken the temporary's resource. // Detach it! sOther.Memory = nullptr; }};};

Page 63: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

rvalue reference 的引入

減少了一些執行時期額外的記憶體配置以及重覆複製資料的負擔對提升運行效能有所幫助尤其對程式庫中的類別而言

Page 64: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

static_assert Declaration (1/2)

在編譯時期針對指定條件檢驗是否成立

constant-expression: 若值評估為 0 ,則編譯失敗並顯示 string-literal 參數之值,反之,則無任何影響

static_assert( constant-expression, string-literal );

Page 65: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

static_assert Declaration (2/2)

應用:

static_assert( sizeof(void *)==4, "64-bit code generation is not supported.");

Page 66: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

static_assert 與傳統方式的比較

在過去有兩種檢查方式條件編譯 + #error 指令 ( 在 preprocessing 階段 )assert 巨集 ( 在 runtime )

#error 無法針對 template 參數進行檢查,因為 class 是在編譯時才會被 instantiatedstatic_assert 是在編譯時期進行檢查,所以可以處理 template 參數的檢查

Page 67: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

nullptr Keyword

nullptr 關鍵字用來表示指向空值的指標解決 0 和指向空值指標的混淆情況提供更直觀更不易出錯的空指標表示方式

void f(int){ printf( "int\n" ); } void f(char*){ printf( "char*\n" ); }

f( NULL ); // int, compile error in GCC f( 0 ); // int f( (char*)0 ); // char* f( (void*)0 ); // compile error

*http://heresy.spaces.live.com/blog/cns!E0070FB8ECF9015F!10891.entry

Page 68: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

概括 C++11 的加強方向

增加編譯、鏈結時的效能增加實際執行的效能提供更高階、更抽象的程式設計方式提供更簡便、更不易出錯的程式設計方式

Page 69: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

使用 C++ AMP 做平行運算

Page 70: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

何謂 C++ AMP?

AMP: Accelerated Massive Parallelism在一個或多個的加速器上執行計算目前,實際的加速器就是 GPU未來,會有其他型式的加速器有了 C++ AMP 後,可以完全使用 C++撰寫應用程式來獲得平行計算的加速

可加速數十倍或更多AMP 基本上是個程式庫附於 Visual Studio 2012 中規格開放,其他平台或編譯器亦可實作

Page 71: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++ AMP 的設計原則

基於 C++ 而非 C能成為主流愈簡化的程式設計模型愈好盡可能少的改動具可攜性

可於任何廠商的硬體上執行通用且不會過期

使用不同的加速器,例如雲端上的加速器開放

規格開放

Page 72: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

CPU vs. GPU

較低的記憶體頻寬高耗能中度平行化較深的指令管線隨機存取支援通用型的程式通用型的程式設計

較高的記憶體頻寬低耗能高度平行化較淺的指令管線循序存取支援平行資料操作的程式專用型的程式設計

Page 73: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

GPGPU

General-Purpose computing on Graphics Processing Units 也稱 GP²U 傳統的 GPU通常是處理和圖形有關的計算由於現代 GPU 具有強大的並行處理能力,使得 GPU也可以用來處理一些通用類型的資料尤其是面對單一指令多資料流( SIMD )的情況

目前,OpenCL 是現存的 GPGPU 計算語言Nvidia 的 CUDA 則是現成的封閉式框架

Page 74: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

異質性計算( Heterogeneous Computing )

在同一計算系統中,使用不同指令集和架構的計算單元來組成計算方式,即為異質性計算常見的計算單元包括像是

CPU, GPU, DSP, ASIC, FPGA … 等等不同類型計算單元的長處各不盡相同異質性計算則嘗試綜合各自的長處

例如 GPU擅長平行計算組合 CPU+GPU 計算的系統,即屬異質性計算系統

Page 75: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

GPU所能容納的執行緒數-例

NVIDIA GTX 69016個多處理器每個多處理器有 192個 CUDA核心每個多處理器的最大執行緒數是 2048可同時容納最多 32,768個執行緒

NVIDIA GTX 560 SE9個多處理器每個多處理器有 32個 CUDA核心每個多處理器的最大執行緒是 1536可以同時容納最多 13,824個執行緒

*http://www.infoq.com/cn/articles/cpp_amp_computing_on_GPU

Page 76: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

程式庫型式的 C++ AMP (1/2)

附於 Visual Studio 2012之中是個 STL-like 的程式庫#include <amp.h> 後取用Namespace: concurrency新類別

array, array_newextent, indexaccelerator, accelerator_new

Page 77: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

程式庫型式的 C++ AMP (2/2)

新函式parallel_for_each()

新關鍵字(或說同名但新的用法)restrict用來告訴編譯器檢查 GPU ( DirectX )

Page 78: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

parallel_for_each

程式庫的入口接收參數所需的執行緒數在每個執行緒中執行的函式或 labmda (必須是 restrict(amp) )

將工作送至加速器返回 – 不會有遲滯或等待

Page 79: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Hello AMP: 陣列相加#include <amp.h>using namespace concurrency;

void AddArrays(int n, int * pA, int * pB, int * pSum){ array_view<int,1> a(n, pA); array_view<int,1> b(n, pB); array_view<int,1> sum(n, pSum); parallel_for_each( sum.extent, [=](index<1> i) restrict(amp) { sum[i] = a[i] + b[i]; } );}

void AddArrays(int n, int * pA, int * pB, int * pSum){

for (int i=0; i<n; i++)

{ pSum[i] = pA[i] + pB[i]; }

}

Page 80: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

C++ AMP 程式設計的基本元素array_view

將資料包裝成可於加速器上操作的型式

parallel_for_each在每個執行緒上執行一次函式或lambda

extent執行 lambda 的執行緒個數及結構形狀

index執行 labmda 的執行緒 ID ,做為資料的索引

restrict(amp)表示 amp限制

void AddArrays(int n, int * pA, int * pB, int * pSum){ array_view<int,1> a(n, pA); array_view<int,1> b(n, pB); array_view<int,1> sum(n, pSum); parallel_for_each(

sum.extent, [=](index<1> i) restrict(amp) { sum[i] = a[i] + b[i];

} );}

操作

Page 81: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

extent<N>: N 維空間的大小

Page 82: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

index<N>: N 維空間中的點

Page 83: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

array_view<T, N>

檢視 CPU或 GPU上既存的資料元素型別 T ,並有 N 維需指定 extent矩形隨處可存取(自動同步)

vector<int> v(10);

extent<2> e(2,5); array_view<int,2> a(e, v);

//above two lines can also be written//array_view<int,2> a(2,5,v);

index<2> i(1,3);

int o = a[i]; // or a[i] = 16;//or int o = a(1, 3);

Page 84: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

restrict(amp) 的限制

僅能呼叫其他同為 restrict(amp) 的函式所有的函式都必須是可 inline僅能使用支援 amp 的型別

int, unsigned int, float, double, bool上述型別構成的 struct 及陣列

指標及參照的限制Lambda 不能是 capture by reference或是capture pointer參照及單向指標僅能做為區域變數及函式的引數

Page 85: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

restrict(amp) 的限制

Page 86: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

array<T, N>

多維陣列,元素型別 T ,N 維存於特定加速器中的儲存空間Capture by reference自行指定的複製動作和 array_view<T, N>相近的介面

vector<int> v(8 * 12);extent<2> e(8,12);accelerator acc = …array<int,2> a(e,acc.default_view);copy_async(v.begin(), v.end(), a);

parallel_for_each(e, [&](index<2> idx) restrict(amp) { a[idx] += 1;});copy(a, v.begin());

Page 87: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

parallel_for_each 的非同步特性

呼叫完立即返回當嘗試透過 array_view存取處理中的資料時,若尚未運行完畢,則會等待,直到運算結束為止可運用 array_view 的synchronize_async()函式來處理計算的完成事件

std::shared_future<void> synchronize_async() const;

Page 88: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

撰寫 C++ AMP 程式簡單直覺

撰寫 C++ AMP 程式的步驟建立 arr ay_view物件呼叫 parallel_for_each利用 array_view物件得到計算結果

CPU和 GPU之間的溝通細節,皆由程式庫包裝記憶體的分配和釋放資料的同步GPU 執行緒的規劃和管理

Page 89: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Visual Studio 2012 對 C++ AMP 的除錯支援

中斷點偵錯類型變數值及 call stack 的察看GPU 的執行緒狀態平行計算資料的察看

Page 90: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

中斷點的設定

*Kate Gregory, “C++ Accelerated Massive Parallelism in Visual C++ 2012”

可停在 CPU或 GPU 的中斷點GPU 的中斷點僅Windows 8 支援

Page 91: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

除錯類型設定

Page 92: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

變數值及 call stack 的察看

Page 93: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

GPU 的執行緒狀態察看

Page 94: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

平行計算資料的察看

Page 95: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

開發 / 執行 C++ AMP 的條件

開發Visual Studio 2012支援 DirectX 11 的顯示卡Windows 8 作業系統

執行Windows 7/Windows 8支援 DirectX 11 的顯示卡

Page 96: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

看待 C++ AMP 程式的效能問題

愈包裝的夠高階夠抽象的程式庫愈有提升效能的可能性基於 C++ AMP 的程式本身結構夠簡單效能取決於 C++ AMP 程式庫的實作當然還有底層的硬體條件只要程式庫被專家最佳化了,應用程式就變快了

Page 97: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

Connect. Share. Discussshttp://www.microsoft.com/taiwan/techdays2012/

Microsoft Certification & Training Resources

http://www.microsoft.com/learning/zh/tw/

Resources for IT Professionals

http://social.technet.microsoft.com/Forums/zh-tw/categories

/

Resources for Developershttp://social.msdn.microsoft.com/Forums/zh-tw/categories

/

Resources

Page 98: 認識 C++11 新標準及使用 AMP 函式庫作平行運算
Page 99: 認識 C++11 新標準及使用 AMP 函式庫作平行運算

請協助完成「本課程問卷」,並在離開教室時交給工作人員!

填妥大會背包中的大會問卷,可於活動第三天兌換問卷禮哦!

感謝您的合作。

Page 100: 認識 C++11 新標準及使用 AMP 函式庫作平行運算