国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

利用Lambda函數提高C++編程代碼性能

2024-07-21 02:30:28
字體:
來源:轉載
供稿:網友

使編譯器以及操作系統從正在創建的應用中榨取更高性能的關鍵在于提供充足的有關代碼意圖的信息。在充分了解這個代碼意圖實現的功能等信息的情況下, 就有可能將代碼在編譯時和運行時的并行吞吐量最大化,令開發者可以將更多精力放在他們所關注的商業領域的問題,將重量級的多核多處理器的任務計劃交托給編 譯器,運行時庫以及操作系統中的基礎設施代碼來處理。

循環函數是很重要的一個環節,因為在所有可用的硬件資源中,被分離的循環中的各個部分在一般情況下能夠提供更高的應用性能。考慮這樣一個小情況:迭代選定組合中的全部元素以求得總和。最簡單最直接的執行方法如下:

std::vector<int> v;
v.push_back(1);
v.push_back(5);
int total = 0;
for (int ix = 0; ix < v.size(); ++ix){
total += v[ix];
}

以上的例子十分便于人工讀寫。對于熟悉c語言家族語法的開發者而言,這個循環的意圖也十分容易理解。然而對于編譯器以及運行時庫的組合而言,要在多個線程之間計劃好這個循環,它還需要類似于openmp編譯指示一類的指示來告訴它哪里有優化的空間:

std::vector<int> v;
v.push_back(1);
v.push_back(5);
int total = 0;
#pragma omp for
for (int ix = 0; ix < v.size(); ++ix){
#pragma omp atomic
total += v[ix];
}

第一個openmp指示提出了多線程運行for循環的要求,而第二個omp atomic指示則被用來防止多線程同時向總數變量上寫入。對于openmp,在msdn庫的參考文檔中有關于所有指示的詳細介紹。

如果使用了聲明式循環技巧,那么將并行方法應用在矢量求和上則更加干凈簡單。stl for_each函數是一個理想的替代品,以上的例子則被改寫如下:

class adder{
private:
int _total;
public:
adder() : _total(0) {}

void operator ( ) ( int& i )
{
  _total += i;
}

operator int ( )
{
  return  _total;
}
};

void vectoradd()
{
std::vector<int> v;
v.push_back(1);
v.push_back(5);
int total = std::for_each(v.begin(), v.end(), adder());
}
這里,具體的for循環被舍棄,求矢量和的代碼變得干凈了一些;但是由于需要使用一系列運行符來定義一個類,這使得這個解決方案被大大的復雜化了。 除非代碼庫中還有大量類似的求和聲明,否則一個開發者是不會僅僅為了stl for_each的那點好處而多花費功夫去定義一個新類的。

|||

仔細檢查這個adder類,可以很明顯的看出其大部分內容都僅僅是用來滿足將實例用作函數對象的調用條件的。這個類中唯一起到計算作用的僅僅是那一 行_total += i。考慮到這一點,c++ 0x提供了一個被大大簡化了的、以lambda函數方式來實現的語法技巧。lambda函數移除了對這些搭架子代碼的需求,并允許在另外的一個聲明中定義 一個謂詞函數。由此,vectoradd函數可以被改寫如下:

std::vector<int> v;
v.push_back(1);
v.push_back(5);
int total = 0;
std::for_each(v.begin(), v.end(),
[&total](int x) {total += x;}
);

lambda函數的語法相當直截了當。方括號中的第一個lambda元素告訴編譯器,本地變量total通過引用被捕捉(這樣的情況下最好用引用捕 捉,因為你需要矢量和的結果在for_each之后仍然有效),而lambda的第二部分則是參數列表。lambda的最后一部分是函數的主體,這個例子 中就是將參數x的值加到變量total中去。

如果在lambda函數中沒有需要捕捉的變量,或者只需要捕捉變量的一個副本,那么函數開始的方括號可以留空:

std::for_each(v.begin(), v.end(), [](int x) {
std::cout << x << std::endl;
});

混合的捕捉方法也可以使用:

int total = 0;
bool displayinput = true;
std::for_each(v.begin(), v.end(), [&total, displayinput](int x) {
total += x;
if (displayinput){
  std::cout << x << std::endl;
}
});

這里,變量displayinput通過副本被捕捉。visual c++編譯器在編譯時會報錯c3491:'displayinput':一個在lambda函數內數值被改變的變量無法在一個非可變lambda中通過數值被捕捉。

lambda函數中還有一個值得注意的地方,就是它的返回值類型。編譯器一般會盡可能的(也是被要求的)推斷lambda表達式的返回值類型,不過 對于復雜的多行表達式而言,有可能會需要確切的聲明返回值類型。返回值類型聲明通過在lambda函數參數和函數主體之間添加-﹥運行符以及需要被聲明的 返回值類型來實現:

std::for_each(v.begin(), v.end(),
[&](int x)->void {total += x;});
}

c++中有了lambda函數,這令聲明式編程以及使用stl運算法則變得更加簡潔。lambda函數允許在函數主體內的可執行代碼字行間進行定義。在為 編譯器提供強大的優化提示之外,lambda函數所推崇的代碼模式可以令人更加簡單的理解哪段代碼是要實現怎樣的功能。visual c++ 2010將帶來在并行處理上的顯著功能提升,而lambda函數將是具體實現這些提升的重要手段之一。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 盱眙县| 阿勒泰市| 金华市| 平谷区| 淄博市| 平舆县| 当雄县| 巴中市| 于都县| 巴楚县| 双城市| 福泉市| 社会| 忻州市| 来安县| 惠安县| 安徽省| 青浦区| 广德县| 玉环县| 天全县| 通许县| 新乡县| 潜山县| 衢州市| 莱芜市| 鄯善县| 上高县| 忻城县| 陇南市| 化隆| 湖州市| 清流县| 吉林省| 耒阳市| 玉山县| 林州市| 新化县| 资中县| 兰坪| 南京市|