日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

从编译到执行,C++如何开发SIMD友好的代码?

發布時間:2023/12/10 c/c++ 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 从编译到执行,C++如何开发SIMD友好的代码? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一:名詞解釋


Flynn分類法

Flynn于1972年提出了計算平臺的Flynn分類法,主要根據指令流和數據流來分類。按照Flynn分類法,計算平臺共分為四種類型。

1.單指令流單數據流機器(SISD)

?

2.單指令流多數據流機器(SIMD)

?

3.多指令流單數據流機器(MISD)

?

4.多指令流多數據流機器(MIMD)

?

標量處理器

標量處理器是一種最簡單的計算機處理器類型。這類處理器在同一時間內只處理一條數據(整數或浮點數)。標量處理器是一種單指令流單數據流(SISD)處理器。

向量處理器

當今大多數商業 CPU 都包括一些向量處理器指令,較為典型的是 SIMD。從運算上說,標量機只是一個數一個數地進行計算,而向量機則能夠對一批數據同時進行加工處理。因此,向量機比標量機的運算速度快,更適合于演算數據量多的大型科學、工程計算問題。

并行

不同于并發的概念,并發偏重于多個任務交替執行,而多個任務之間有可能還是串行。真正意義上的“同時執行”。同時做很多事情。

SIMD

讀做(sim-dee),單指令流多數據流(英語:Single Instruction Multiple Data,縮寫:SIMD)是一種采用一個控制器來控制多個處理器,同時對一組數據(又稱“數據向量”)中的每一個分別執行相同的操作從而實現空間上的并行性的技術。實現這種架構的并行處理機,每次都執行相同的指令,對不同的數據進行處理。這種計算機適合處理矩陣計算。

keypoints:

1.SIMD結構的CPU有多個執行部件,但都在同一個指令部件的控制之下,中央控制器向各個處理單元發送指令,整個系統只要求有一個中央控制器,只要求存儲一份程序,所有的計算都是同步的。

2.以加法指令為例,單指令流單數據流(SISD)型CPU對加法指令譯碼后,執行部件先訪問主存,取得第一個操作數,之后再一次訪問主存,取得第二個操作數,隨后才能進行求和運算;而在SIMD型CPU中,指令譯碼后,幾個執行部件同時訪問主存,一次性獲得所有操作數進行運算。

3.SIMD不是一種具體的指令格式,經歷了mmx->sse->avx這樣的發展趨勢,但它們都屬于SIMD,SIMD更像是一種滿足某種規范的技術架構總稱。

SSE

Intel在1999年引入了SSE指令,SSE是"Streaming SIMD Extention"(流SIMD擴展)的縮寫,SSE是Streaming SIMD Extensions(流SIMD擴展)的縮寫。是由 Intel公司,在1999年推出Pentium III處理器時,同時推出的新指令集。SSE是一種SIMD指令集。SSE有8個128位寄存器,XMM0 ~XMM7。這些128位元的寄存器,可以用來存放四個32位的單精確度浮點數。SSE的浮點數運算指令就是使用這些寄存器。

keypoints:

-Intel的初代SIMD指令集是MMX,Multi-Media Extension, 即多媒體擴展,因為它的首要目標是為了支持MPEG視頻解碼。后來Intel進一步實現了SSE, SSE2~SSE4指令集,給了他們單獨的寄存器,之后MMX就停掉了。

-SSE包含70條新的指令,其中大部分指令用于單精度 浮點數據。當對多個數據對象執行完全相同的操作時,SIMD指令可以大大提高性能。

-SSE隨后被英特爾擴展為SSE2,SSE3,SSSE3和SSE4。-SSE功能歷經幾代,最新的版本為AVX(advanced vector extension)

-SSE中大部分指令要求地址是16byte對齊的。-要能夠使用 Intel 的 SIMD 指令集,不僅需要當前 Intel 處理器的硬件支持,還需要編譯器的支持。

-由于SIMD指令有多個版本,每個版本支持的指令集不同。所以如果你的軟件要支持更多的CPU,就要在使用SIMD指令之前知道當前指令運行所在的CPU是否支持這條指令。

-SSE發展到SSE5戛然而止。這里有故事,2007年8月,AMD搶先宣布了SSE5指令集(之前從SSE到SSE4均為Intel制定),Intel火大,轉而另起爐灶,2008年4月,Intel公布了AVX指令集規范,隨后開始不斷進行更新。

?

二:C++如何開發SIMD友好的代碼?


使用SIMD技術的開發方法業內有如下幾種:

1.使用著名的IPP庫,IPP的全稱是Intel Integrated Performance Primitives

2.方法是使用編譯器的自動向量化(Auto-vectorization)支持。

3.使用編譯器指示符(compiler directive),如使用英特爾的C/C++編譯器(ICC)編譯如下代碼,那么ICC便會對#pragma simd指示符下面的for循環做向量化

4.使用Cilk技術。

5.使用編譯器的內建函數(intrinsic),例如要使用要使用SSE3,#include,如果不關心使用那個版本的SSE指令,則可以包含所有#include

6.直接使用匯編語言編寫匯編函數,C++調用匯編函數

?

編寫高效程序需要做到以下幾點:

第一,必須選擇一組適當的算法和數據結構。

第二,必須編寫出編譯器能夠有效優化以轉換成高效可執行代碼的源代碼。

參考:http://sci.tuomastonteri.fi/programming/sse

三:從編譯到執行,發生了什么事情?


我們剛才提到了C++代碼,也提到了指令集。

提到了如何寫SIMD友好的C++代碼和SSE指令有多神奇。

可是,這一切是怎么發生的呢?

從C++源代碼編譯生成可執行代碼,到CPU運行load到內存的這些代碼。

這中間,發生了什么事情?

我們來聊聊CPU指令集和GCC編譯的那點兒事兒。

先來溫習一下計算機體系結構的基礎知識:

指令 = 操作碼 + 操作數

操作碼:表示指令要完成的工作,如存數,取數。

操作數:操作對象的內容或者所在的單元格地址。

計算機工作的過程實際上是快速的執行指令的過程,當計算機在工作時,有兩種信息流在流動。一種是數據流,通常是各種原始數據、中間結果等。一種是控制流,是由各種控制指令構成的。

指令的執行過程:

1.取指令,從內存儲器取出指令到指令寄存器。

2.分析指令,對指令寄存器中存放的指令進行分析,由譯碼器對操作碼進行譯碼。將指令的操作碼轉換成相應的控制電信號,并由地址碼確定操作數的地址。

3.執行指令。由操作控制線路發出的完成該操作所需的一系列控制信息。用以完成該指令所需的操作。

4.為執行下一條指令做準備。形成下一條指令的地址。指令計數器指向存放下一條指令的地址,最后控制單元將執行結果寫入內存。

上述完成一條指令的執行過程叫做一個“機器周期”;計算機在運行時,CPU從內存讀取一條指令到CPU內執行,指令執行完,再從內存讀取下一條指令到CPU執行。CPU不斷的取指令、分析指令、執行指令,再取下一條指令,這就是程序的執行過程。

再看高級語言編譯過程,是將源代碼轉換為機器可認識代碼的過程。編譯程序讀取源程序(字符流),對之進行詞法和語法的分析,將高級語言指令轉換為功能等效的匯編代碼,再由匯編程序轉換為機器語言,并且按照操作系統對可執行文件格式的要求鏈接生成可執行程序。

C/C++源代碼編譯成相應平臺下的可執行文件需要經過如下步驟:

1、預處理

2、編譯

3、匯編

4、鏈接

接下來我們探索一下C++編譯的機器碼如何和SIMD掛上了鉤的?

首先,需要被執行的機器碼先要被OS調度到內存之中, 程序執行時, 機器碼依次經過了Memory--Cache--CPU fetch, 進入CPU流水線, 接著就要對它進行譯碼了, 譯碼工作生成的是CPU內部數據格式, 微碼。特別需要注意的是:CPU不需要任何形式的存儲介質去存儲指令集, 因為"譯碼"這個步驟就是在對指令集里規范的機器碼做解碼。具體的指令編程機器碼后就會變成數字電路的開關信號。其中某幾段會作為控制信號,控制其他部分的數據走不同的電路以執行運算。

關鍵點就在這里了,從匯編到機器碼這步是匯編程序翻譯的。匯編程序知道某條指令要翻譯成什么樣的機器碼。匯編的前提是一定要有格式,支持什么指令, 指令帶什么限制條件, 用什么操作數, 用什么地址, 其實都是指令集規范的內容, 如果寫錯了, 就無法翻譯成機器碼。

比如C++編譯后的匯編文件中某條支持SSE的某條匯編語句:

movaps? %xmm1, %xmm4

翻譯成如下的機器碼:

26 66 c7 84 c8 44 33 22 11 78 56

到真正執行的層面,CPU將指令(一個由0,1構成的字符串)輸入譯碼電路,譯碼電路根據指令集的描述,生成各種控制信號。

控制整體晶體管邏輯電路開始工作。這個機器碼就是SIMD的機器碼,在單個時鐘周期里能夠并行的從內存中讀取和計算數據。

FAQ:

1.ClickHouse怎樣用到SIMD技術?

目前Clickhouse通過編譯器的內建函數(intrinsic)開發的方式來利用到SIMD技術。

2. ClickHouse為什么不用更牛逼的MIMD ?

MIMD和SIMD只是體系結構的兩種概念,并不是說采用SIMD支持的指令集就無法使用MIMD操作。實現SIMD概念的SSE3(舉例),就支持某些MIMD操作。另外,目前筆者也沒有發現有C++能夠支持MIMD機器的優化。

注:由于每個執行單元的指令流都是相同的,SIMD模式將指令的獲取時間均攤到每一個執行單元。但是,當指令流出現分支,指令就會被序列化。而MIMD模式的設計主要是為了處理不同指令流,當指令流出現分支,它不需要對線程進行阻塞。然而它需要更多指令存儲以及譯碼單元,這就意味著硬件需要更多的硅,同時,為了維持多個單獨的指令序列,它對指令帶寬的需求也非常的高。一般使用SIMD與MIMD的混合模式才是最好的方案。用MIMD的模式處理控制流,用SIMD的模式處理大數據,在CPU上使用SSE/MME/AVX指令擴展集時就是采用的SIMD與MIMD的混合模式

3.如何編寫可以自動矢量化的代碼?

參考:http://www.jianshu.com/p/186339c16e8c

這個例子說明,現在處理器具備相當的計算能力,但是我們需要按照特定程式化的方式來編寫程序,就可以將這些能力誘發出來。

題外話:

C++語言之父Bjarne在“2016 C++及系統軟件技術大會”上。做了題為《What C++ is and what it will become》的演講。

what is C++ --

他用兩行話描述了C++是什么:

1.“Direct map to hardware” -- 直接映射到硬件

2.“Zero overhead abstraction” -- 0負擔抽象

對于1,C++的字節對齊以及多指令集的支持,使之能夠直接翻譯對應到CPU的指令。C++的數據類型也可以直接對應到CPU支持的數據類型。無需進行轉換。可謂效率奇高。

對于2,今天的JAVA、C#都有抽象,但有些語言為了抽象付出的代價很大,資源消耗多,運行速度慢,C++基本0負擔,無額外開銷。

what it will become --

提到了10項內容,第8項提到了在語言層面支持SIMD向量和并行化算法。

期待語言層面的SIMD支持和并行算法封裝。這樣,在編寫能夠支持SIMD優化代碼時,可能就不用關注太多的細節了。



作者:_金科
鏈接:https://www.jianshu.com/p/6b1bbbefbb70
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。

總結

以上是生活随笔為你收集整理的从编译到执行,C++如何开发SIMD友好的代码?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。