2018-03-01 【Linux下在GCC環(huán)境使用SIMD】

什么是SIMD

SIMD的全稱是Single Instruction Multiple Data (單指令多數(shù)據(jù)流)队橙。

在支持SIMD的CPU中拦坠,包含著一些特別寬的寄存器(比如512位)连躏。通過特別的指令,可以在這些寄存器上執(zhí)行指定操作贞滨。這些操作通常是對正常寄存器(比如64位)上操作的拓展入热,可以理解為一條指令同時操作了多個正常寄存器,也就是所謂的SIMD了晓铆。

SIMD的性能

做個簡單的除法就能知道勺良,512位的寄存器相比64位寄存器,速度提升了8倍骄噪。

但是實際情況不僅僅是如此尚困。在SIMD的指令中,還包括了一些非常奇妙的指令链蕊,比如計算正態(tài)分布的累積分布函數(shù)和其反函數(shù)的指令事甜。在看到它們的時候谬泌,我心里吼了一句:“還有這種操作!”逻谦。這些特化的指令在特別的場景下就是神器掌实。

怎么用SIMD

首先,我們是在Linux的GCC編譯器上使用SIMD指令跨跨。在這個條件下潮峦,有兩個途徑:

  • 嵌入式匯編
  • Intrinsics

嵌入式匯編不是今天的主題。我今天主要記錄一下Intrinsics怎么用勇婴。不管使用哪種方法忱嘹,有一個網(wǎng)站是一定要收藏的:Intel Intrinsics Guide

它給出了SIMD指令集的各個子集: MMX, SSE耕渴,SSE4.2拘悦,AVX2等等。同時橱脸,它給每個指令都打上一些標簽用于檢索:Load础米,Store,Cast添诉,Arithmetic 等等屁桑。它還給出了每個指令的等價操作和匯編指令。

具體地說栏赴,在C語言中使用SIMD涉及三個方面:

  • 頭文件
  • 函數(shù)調(diào)用
  • 編譯選項

頭文件和函數(shù)調(diào)用很好辦蘑斧,它歸屬于Intel的規(guī)范。在Intel Intrinsics Guide中须眷,每條指令需要的頭文件都有標注竖瘾,按圖索驥即可。

編譯選項則屬于GCC的規(guī)范花颗。 i386 and x86-64 Options 將相關選項包含在內(nèi)捕传,但是更寬一些。每條指令都有所屬的指令集(比如SSE4.2)扩劝,當使用到該指令后庸论,就要在鏈接器的選項中加上相關的項 (比如-msse4.2) 。

選項的命名很直接棒呛,在 i386 and x86-64 Options 里搜索 -mmmx 就可以跳到SIDM選項比較集中的區(qū)域葡公,很容易就能確定需要的選項是什么。

內(nèi)存對齊

使用SIMD指令的范式很簡單:

  • 用SIMD指令条霜,將數(shù)據(jù)從內(nèi)存導入特殊寄存器
  • 用SIMD指令,在特殊寄存器間進行運算
  • 用SIMD指令涵亏,將運算結(jié)果導出回內(nèi)存

這里涉及到一個問題宰睡,就是導入導出使用到的內(nèi)存必須滿足特殊的對齊條件蒲凶。比如使用了128位(16字節(jié))的SIMD,則內(nèi)存首地址必須能被16整除拆内。如果不滿足該條件旋圆,在導入數(shù)據(jù)時程序會引發(fā)段錯誤退出。

在C中麸恍,獲得特定對齊方式的動態(tài)內(nèi)存灵巧,使用的函數(shù)是來自stdlib.hvoid* aligned_alloc(size_t alignment, size_t size)

使用案例

// Filename: main.cpp
#include <cstdlib>
#include <cstdio>
#include <immintrin.h>
using namespace std;

void print(float* data, int n) {
  for (int i = 0; i < n; i ++) {
    printf("%f ", data[i]);
  }
  printf("\n");
}

int main() {
  const int WIDTH = 256;
  const float x = 0.2;

  int n = WIDTH/8/sizeof(float);
  float* w = (float*) aligned_alloc(64, sizeof(float)*n);
  float* y = (float*) aligned_alloc(64, sizeof(float)*n);
  
  // 生成數(shù)據(jù)
  for(int i = 0; i < n; i ++) {
    w[i] = rand();
  }
  print(w, n);
  
  // y_i = w_i * x
  __m256 _x = _mm256_set1_ps(0.2);
  __m256 _w = _mm256_load_ps(w);
  __m256 _y = _mm256_mul_ps(_x, _w);
  _mm256_store_ps(y, _y);

  print(y, n);
  free(y);
  free(w);
}

編譯的指令如下:

g++ -o a.out -mavx main.cpp
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末抹沪,一起剝皮案震驚了整個濱河市刻肄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌融欧,老刑警劉巖敏弃,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異噪馏,居然都是意外死亡麦到,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門欠肾,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瓶颠,“玉大人,你說我怎么就攤上這事刺桃〈饬埽” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵虏肾,是天一觀的道長廓啊。 經(jīng)常有香客問我,道長封豪,這世上最難降的妖魔是什么谴轮? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮吹埠,結(jié)果婚禮上第步,老公的妹妹穿的比我還像新娘。我一直安慰自己缘琅,他們只是感情好粘都,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著刷袍,像睡著了一般翩隧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上呻纹,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天堆生,我揣著相機與錄音专缠,去河邊找鬼。 笑死淑仆,一個胖子當著我的面吹牛涝婉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔗怠,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼墩弯,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了寞射?” 一聲冷哼從身側(cè)響起渔工,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怠惶,沒想到半個月后涨缚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡策治,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年脓魏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片通惫。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡茂翔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出履腋,到底是詐尸還是另有隱情珊燎,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布遵湖,位于F島的核電站悔政,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏延旧。R本人自食惡果不足惜谋国,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望迁沫。 院中可真熱鬧芦瘾,春花似錦、人聲如沸集畅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挺智。三九已至祷愉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背谣辞。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工迫摔, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人泥从。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像沪摄,于是被迫代替她去往敵國和親躯嫉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容