SSE與AVX指令集加速

SSE與AVX指令集

SSE指令集是英特爾提供的基于SIMD單指令多數(shù)據(jù)钥勋,也就是說同一時間內,對多個不同的數(shù)據(jù)執(zhí)行同一條命令)的硬件加速指令勺馆,通過使用寄存器來進行并行加速微猖。經過幾代的迭代晓避,最新的SSE4已經極大地擴展了指令集的功能业踏,并且隨后已經從128位寄存器繼續(xù)擴展到256位的指令盛撑。

想要使用SSE或AVX指令集檬姥,需要包含以下頭文件

#include <mmintrin.h>   //mmx, 4個64位寄存器
#include <xmmintrin.h>  //sse, 8個128位寄存器
#include <emmintrin.h>  //sse2, 8個128位寄存器
#include <pmmintrin.h>  //sse3, 8個128位寄存器
#include <smmintrin.h>  //sse4.1, 8個128位寄存器
#include <nmmintrin.h>  //sse4.2, 8個128位寄存器
#include <immintrin.h>  // avx, 16個256位寄存器

1. intrinsics

intrinsic是將xmm曾我、sse等指令封裝,變成內聯(lián)函數(shù)以減少函數(shù)調用的一種操作健民,具體語法如下:

#pragma intrinsic(function_name)

intrinsic只允許內聯(lián)諸如標準庫函數(shù)或部分函數(shù)抒巢,是通過內聯(lián)底層標準函數(shù)而減小開銷的,不是所有函數(shù)都能使用秉犹。而指令集SSE蛉谜、AVX等屬于封裝好的標準內聯(lián)函數(shù),導入頭文件之后可直接使用崇堵。

2. SSE指令集

完整的SSE指令集可以點擊此處查看悦陋。

我們主要關注SSE指令集在C和C++上的應用。在工程中筑辨,對于128位的寄存器俺驶,最實用的操作就是當做4個32位單精度的浮點數(shù)。其中棍辕,包裝指令集是指矢量指令集暮现,單個指令會對VALU中的數(shù)據(jù)都進行同一指令操作;而標量指令是指指令只對寄存器最低位的數(shù)據(jù)進行操作楚昭。

SSE架構

以下是常用的函數(shù)栖袋。

  1. 編譯語句

    g++ -msse4 filename.cpp
    
  1. 編程實例

    對于多核處理器,每一個核都有著自己的緩存抚太,以及FPU塘幅、VALU模塊昔案。VALU允許同時操作4個浮點數(shù),通過SSE指令集加速一個128位矢量的FDTD程序电媳。

    1. 相加的簡例

      /* 對于變量v1與v2各有x踏揣、y、z匾乓、w四個屬性捞稿,vec_res的結果便是v1、v2對應的屬性相加 */
      
      // 標量版本
      vec_res.x = v1.x + v2.x;
      vec_res.y = v1.y + v2.y;
      vec_res.z = v1.z + v2.z;
      vec_res.w = v1.w + v2.w;
      
      // VALU版本
      movaps xmm0, [v1];                    // 將要移動v1變量到xmm0寄存器中
      xmm0 = v1.w | v1.z | v1.y | v1.x ;    // 將4個值加載到寄存器中
      addps xmm0, [v2];                     // 將要對xmm0和v2變量進行相加
      xmm0 = v1.w + v2.w | v1.z + v2.z | v1.y + v2.y | v1.x + v2.x ;  // 相加
      movaps [vec_res], xmm0;               // 將寄存器的值賦給vec_res
      
    2. C++矢量相乘簡例

      注意:在編譯時必須使用g++編譯器拼缝,同時娱局,SSE指令集有SSESSE2咧七、SSE3衰齐、SSE4幾種,越新的版本功能就越多继阻,可以通過在使用g++編譯鏈接時娇斩,加上-msse4使用SSE4指令集,其他以此類推穴翩。

      /* 使用SSE指令進行矢量相乘加速 */
      
      #include<iostream>
      // 使用SSE指令集需要的頭文件
      #include<xmmintrin.h>
      using namespace std;
      
      int main()
      {
          // VALU加速版本: 0m0.004s
          __m128 a, b;
      
          a = _mm_set_ps(1, 2, 3, 4);
          b = _mm_set_ps(1, 2, 3, 4);
      
          __m128 c = _mm_add_ps(a, b);
          
          for(int i=0; i<4; i++)
          {
              cout << a[i] << endl;
          }
          
          return 0;
      }
      

3. 擴展后的AVX指令集

  1. 新增特性

    • 將 128 位 SIMD 寄存器擴展至 256 位。
    • 添加了 3 操作數(shù)非破壞性運算锦积。之前在 A = A + B 類運算中執(zhí)行的是 2 操作數(shù)指令芒帕,它將覆蓋源操作數(shù),而新的操作數(shù)可以執(zhí)行 A = B + C 類運算丰介,且保持原始源操作數(shù)不變背蟆。

    需要啟用AVX指令時,編譯必須加上 -mvax哮幢,否則會報錯带膀。頭文件中包含的所有函數(shù)在 此處 可以查看。

  1. 編譯語句:

    g++ -mavx filename.cpp
    
  1. YMM寄存區(qū)

    相比于早年128位的XMM寄存器橙垢,英特爾AVX提供了256位的YMM寄存器垛叨,而XMM被視作了相應的底層部分。

YMM寄存器
  1. 對齊

    當源數(shù)據(jù)是關于n位對齊(也就是能完整地以n為一個單位切分)地存入YMM寄存器中柜某,稱之為數(shù)據(jù)對齊嗽元。對于SSE運算來說,默認必須保證數(shù)據(jù)對齊(雖不必須喂击,但最好保證剂癌,某些操作并不提供非對齊的操作版本)。

  1. 盡量不要VEX與XMM指令混用

    混合使用舊的僅 XMM 的指令和較新的AVX 指令會導致延遲 翰绊,所以不要將 VEX 前綴的指令和非 VEX 前綴的指令混合使用佩谷,以實現(xiàn)最佳吞吐量 旁壮。

  1. 相加的例子

    #include<iostream>
    #include<immintrin.h>   // avx
    using namespace std;
    
    int main()
    {
        __m256 a, b;
        
        /*
        Note:
        隨著位數(shù)的變化,寄存器可以存放的同一類型數(shù)據(jù)的個數(shù)也發(fā)生了翻倍谐檀,
        在128位的SSE中抡谐,_mm_set_ps()可以計算4個float型數(shù)據(jù),而到了
        256位的AVX中稚补,_mm256_set_ps()可以計算8個float型數(shù)據(jù)童叠。
        */
        
        a =  _mm256_set_ps(1, 2, 3, 4, 5, 6, 7, 8);
        b =  _mm256_set_ps(1, 2, 3, 4, 5, 6, 7, 8);
    
        __m256 c = _mm256_add_ps(a, b);
    
        for(int i=0; i<8; i++)
        {
            cout << c[i] << endl;
        }
    
        return 0;
    }
    
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市课幕,隨后出現(xiàn)的幾起案子厦坛,更是在濱河造成了極大的恐慌,老刑警劉巖乍惊,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杜秸,死亡現(xiàn)場離奇詭異,居然都是意外死亡润绎,警方通過查閱死者的電腦和手機撬碟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莉撇,“玉大人呢蛤,你說我怎么就攤上這事」骼桑” “怎么了其障?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長涂佃。 經常有香客問我励翼,道長,這世上最難降的妖魔是什么辜荠? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任汽抚,我火速辦了婚禮,結果婚禮上伯病,老公的妹妹穿的比我還像新娘造烁。我一直安慰自己,他們只是感情好午笛,可當我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布膨蛮。 她就那樣靜靜地躺著,像睡著了一般季研。 火紅的嫁衣襯著肌膚如雪敞葛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天与涡,我揣著相機與錄音惹谐,去河邊找鬼持偏。 笑死,一個胖子當著我的面吹牛氨肌,可吹牛的內容都是我干的鸿秆。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼怎囚,長吁一口氣:“原來是場噩夢啊……” “哼卿叽!你這毒婦竟也來了?” 一聲冷哼從身側響起恳守,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤考婴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后催烘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沥阱,經...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年伊群,在試婚紗的時候發(fā)現(xiàn)自己被綠了考杉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡舰始,死狀恐怖崇棠,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情丸卷,我是刑警寧澤枕稀,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站及老,受9級特大地震影響,放射性物質發(fā)生泄漏范抓。R本人自食惡果不足惜骄恶,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匕垫。 院中可真熱鬧僧鲁,春花似錦、人聲如沸象泵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽偶惠。三九已至春寿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間忽孽,已是汗流浹背绑改。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工谢床, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人厘线。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓识腿,卻偏偏與公主長得像,于是被迫代替她去往敵國和親造壮。 傳聞我的和親對象是個殘疾皇子渡讼,可洞房花燭夜當晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內容