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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Intel大坑之中的一个:丢失的SSE2 128bit/64bit 位移指令,马航MH370??

發布時間:2023/12/15 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Intel大坑之中的一个:丢失的SSE2 128bit/64bit 位移指令,马航MH370?? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

緣由

  近期在寫一些字符串函數的優化,興趣使然。但是寫的過程中,想要實現?SSE2 128 bit / 64 bit 的按 bit 邏輯位移。遇到了一個大坑,且聽我娓娓道來。

  我并不想用什么馬航370來博眼球。當我寫下這個標題的時候,的確沒有馬航370這個字眼,但是當我寫到一半的時候,突然就冒出了馬航370這幾個字,假設你認真閱讀了我的文章,或許你也應該思考一下。這 128 bit / 64 bit 的位移指令究竟是去哪了?石沉大海了?那不就跟馬航370一樣嗎,是一個謎,一個很很大的謎。。。。

  假設你對 MMX, SSE 位移指令不太懂,能夠先看看:

http://tommesani.com/index.php/simd/44-mmx-shift.html?,

這個比較easy理解,我當初學習 MMX, SSE 指令都是從這里開始的。
可是這個僅僅寫到 MMX 指令集,更新的版本號看后面的。


邏輯位移

對于 MMX, SSE 的位移指令。我們非常自然的想到:

邏輯左移:PSLLW/PSLLD/PSLLQ。Shift Packed Data Left Logical (壓縮邏輯左移)

邏輯右移:PSRLW/PSRLD/PSRLQ,Shift Packed Data? Right Logical (壓縮邏輯右移)

顧名思義,W 指的是Word(字),D 指的 DWORD (雙字),Q 指的是 QWORD (四字),PSLLW 實現的是按 Word 的分組邏輯左移,

PSLLD 是按 DWORD 的分組邏輯左移,PSLLQ 是按 QWORD 實現的分組邏輯左移,這一切看起來都非常 OK 。

這里以邏輯左移為例:


關于詳細的邏輯左移指令的說明,可參考:

http://moeto.comoj.com/project/intel/instruct32_hh/vc256.htm

或者?http://x86.renejeschke.de/html/file_module_x86_id_259.html,

右移也是類似的。在此不再螯述。

?

問題來了

  我們要實現的是 128bit 的邏輯位移,SSE2 里面有?PSLLDQ?/?PSRLDQ?指令,這里 DQ 即是 Double QWORD 的意思。

這不正好是我們須要的 128bit 按 bit 位移嗎?No!。別高興得太早。我們來看看 Intel 的文檔:

PSLLDQ--Packed Shift Left Logical Double Quadword

http://moeto.comoj.com/project/intel/instruct32_hh/vc255.htm

截圖例如以下:


我們看到。非常遺憾。SSE2 并沒有實現 128bit 的按 bit 位移,PSLLDQ 僅僅能實現 128bit 的按 byte 位移。即最小位移量必須是一個 byte (即8個bit),這非常不科學,更不科學的是位移量僅僅能是馬上數。考慮到 Intel 并未真正實現 128bit 數據處理(SSE 大多數指令都僅僅實現了最多 64bit 粒度的數據處理。比如一個雙精度浮點數是 64bit 的)。好吧,我們認了。可是!!可是。!

Intel 你沒搞錯吧。PSLLDQ 的操作數僅僅支持 imm8,imm8 意味著什么?imm8 是 8 位馬上數的意思。那就是說我們僅僅能在匯編里寫死(常數)。不能使用不論什么寄存器來做位移量。What the fu*K??

好吧,這我們也認了。。。CPU 是你設計的,我們拿你沒辦法。說句題外話。假設 PSLLDQ 支持 reg32, reg64 寄存器位移的話, 會方便非常多,由于我們能夠先用 PSLLDQ 位移足夠位數的按 Byte 位移,然后再用 PSLLQ 位移剩下的剩余量(這是后話,為什么要這么用。到后面你就知道),但是,如今這樣的方法都不行。!

這個 imm8 徹底讓我蛋碎了。。。PSLLQ 對于128 bit 寄存器一次僅僅能移 16 位(先破埂了)。那么意味這我們假設要用這樣的方法,要 if / jump 好幾次。

?

大坑開始

好吧,我們退而求其次。既然你不能實現 128 bit 的按 bit 位移。那我們分成兩個 64 bit 的位移來實現好了,無非是多一次推斷,多一次合并。盡管效率沒有直接128 bit 位移的高,可是苦于你沒實現嘛,僅僅能這么干了。。


好吧,我們開始吧。。

。。GO!

。。好了,我們換成 PSLLQ 了,運行PSLLQ xmm0, 32 或 PSLLQ xmm0, ecx (這里ecx的值為32),咦?xmm0怎么全為0了??啊,怎么回事??

我們回過頭來又一次看看 intel 的文檔:


重點看兩個我用紅線框起來的。當 PSLLQ 作用于 64 bit 的寄存器時。我們看到是最大支持 COUNT = 64 位的位移(嚴格意義上講是 max = 63。這個不糾結了。習慣問題。下同)。

可是當 PSLLQ 作用于 128 bit 寄存器時。奇怪的事情發生了,最大僅僅支持 COUNT = 16 位的位移(嚴格意義上是15位),如上圖所看到的。

假設不是又一次看 Intel 的文檔,假設不是調試中發現問題,誰能想到最多僅僅能移15位???Intel 的腦袋是被門夾了嗎??Why??MMX 寄存器上都能夠實現最多 63 位的位移, SSE 寄存器為什么就不能夠?盡管我們知道 MMX 寄存器和 SSE 寄存器是不一樣的,分開的,MMX 寄存器是借用 x87 浮點寄存器來實現 MMX 指令的,但是你在 MMX 寄存器上實現了 64 bit 的位移,為什么在 128 bit 的 SSE 寄存器上卻僅僅能移最多 15 位??你說難以實現,我認了。我不太懂為什么那么難。我們僅僅能認了。但是你卻實現了 128 bit 的按 byte 位移的 PSLLDQ 指令,這又作何解釋??本來顧名思義,PSLLDQ 就來就應該是實現 128 bit 的按 bit 位移,限于歷史原因,這個沒實現我能夠理解。但是你沒有理由在 PSLLQ 作用于 128 bit 的 SSE 寄存器時卻最多僅僅能位移 15 位吧??這真的有那么難嗎??真的難嗎????真的那么難。你又是怎么實現 PSLLDQ 的 128 bit 按 Byte 位移的??

?

尋求答案

帶著這些疑問,我們問了一下 Google 老先生,搜索“128 bit shift”,發現 N 多小伙伴都遇到過這個問題,比如:

Looking for sse 128 bit shift operation for non-immediate shift value

What is SSE !@#$% good for?

#2: Bit vector operations

?

最后,Google老先生告訴了我們一個最好的解答,來自 Intel 的論壇,在這里:

Missing instruction in SSE: PSLLDQ with _bit_ shift amount?


?

是這種,截圖例如以下:


首先,Intel 是承認這個 missing instruction(丟失的指令)的,我們也意識到 missing instruction 無處不在。僅僅是這個有點過分。

上面的回復,大意是:(E文不是太好,用 Google 輔助翻譯的。見諒)

?

Hi Geoff,

  我們的一個project師提供了下面回應,并做一些澄清。

?

  你這個問題是正確的,對于 SIMD(單指令多數據流) 來說。在當前的指令集里,bit 位移是比按 byte 位移難于實現的(指的是 SSE 寄存器

的 128 bit 按 bit 位移)。不幸的是。這不是一個小改變。實現一個這種按 bit 位移指令。

這里有很多其它的改變比簡單的在馬上字節里適應位移

距離--硬件實際完畢按 bit 位移是一個被限制的問題。

  假設你有一個使用案例關于為什么這個操作是實用的,隨著應用程序將受益于這個操作。這是我們有興趣聽到的。普通情況下,我們試圖

設計新的指令來滿足特定的需求。而不是僅僅是提供 "missing instuctions“ (丟失指令)的支持。從實際情況來看,有非常多這種 "missing instuctions“

——更有趣的問題是。假設在實際的應用中應對這些 "missing instuctions“ 所帶來的問題。

博主觀點:

  對于 128 bit 的按 bit 位移比較難以實現。這我能理解,但是 PSLLQ 對于 SSE 的 128bit 寄存器僅僅能最多位移15位我就不能理解了……

SSE2 的 128bit/64bit 位移你在哪里,為什么是15而不是31,63?親愛的馬航MH370,你究竟在哪里?為什么要選擇飛中國的航班?為什么??



解決之道

解決的辦法有非常多種,前面也講過一個。就是:假設你要左移 count 位。先用 PSLLDQ 位移 x * 8 位。 這個是純 128 bit 的位移,然后再用 PSLLQ 位移剩下的 y = (count - x * 8) 位,這里 y 要小于 16。可是因為 PSLLDQ 僅僅能運行imm8馬上數。所以你要先 if / jump 推斷一下 count 的值。分別運行 PSLLDQ xmm0, 32; 或 PSLLDQ xmm0, 16; 或 PSLLDQ xmm0, 8; PSLLDQ xmm0, 4; PSLLDQ xmm0, 2; 以后。再運行 PSLLQ 位移剩下的 Y 位。這里PSLLDQ xmm0, 32或許能夠用別的 SSE Shuffle 指令取代。可是是一樣的,最大的問題是你要先 if 先推斷一下再運行對應的指令。這樣的方法并不見得高效。

我們再來找一些好一點的辦法:

既然,SSE 里我們沒辦法實現 64 bit 的位移,可是 MMX 寄存器里是能夠的,可是我們又要在 SSE 寄存器里實現,那么我們能夠先把數據從 SSE 寄存器里轉移到 MMX 寄存器。位移好了,再合并到 SSE 寄存器里。盡管這個過程有點繁瑣,可是相比上面第一種方法。還是高效了不少,并且有一關鍵的地方,非常多時候。我們要做這個位移,都是接近終于輸出結果的時候,這個時候就不必把數據合并回 SSE 寄存器了,能夠直接用 MMX 寄存器的值作為輸出就可以,這樣又快了一點兒。還不賴。

還有沒有解決的辦法,應該還有,容我再想一想,或者讀者你也想想?有網友貼了 AVX 版的 VPSLLDQ 指令說明,但是相同僅僅支持 imm8 馬上數,并且并非全部人的 CPU 都支持 AVX 的,博主本人的 CPU 就不支持。


后記

我們如今遇到的問題做一個比喻,就是:我們前面有三條路,一條是大路,一條是小路,一條是其它未知的路,我們以為大路(PSLLDQ)最快。于是選擇先走了大路,結果發現直接走是過不去的;轉而選擇小路(PSLLQ),走小路,結果發現有個陷阱,這個陷阱讓我們到不了目的地,僅僅能達到1/4。然后再回過頭來看看大路。大路事實上能夠過去的,可是踩下去以后全是泥潭(僅僅支持馬上數的128位 byte 位移),要走過去,非常艱難。那么我們僅僅能選擇第三條未知的路了(各種其它指令的組合模擬實現)。

Intel 的 MMX, SSE 各種缺失的指令由來已久,指令的設計也是混亂不勘,另一個比較著名的就是僅僅實現了POR, PAND, PANDN(and not),沒有實現 PNOT (即對MMX, SSE寄存器取反),盡管 PNOT 的確能夠用 PANDN 實現(你至少須要2個寄存器),或者用 PCMPEQB xmm0, xmm0 來實現 全置 1 的操作,可是有可能添加了寄存器的占用,可能會添加指令周期,反正是各種不好。盡管影響不算大,可是有時候寄存器捉襟見肘的時候,還是很蛋疼的。

另一點更可笑的是。我跟你說了,你一定會相信 Intel 是荒唐的,我們的確須要的是無符號的邏輯左/右移,可是假設你要實現的是有符號的右移(算術右移),能夠使用 PSRAW/PSRAD 指令 - 壓縮算術右移,另外說一下。不存在算術左移。由于算術左移邏輯左移是一回事。可參考:

http://moeto.comoj.com/project/intel/instruct32_hh/vc257.htm

很可笑的是。在這里。Intel 卻實現了對于 128 bit 寄存器最多 31 位的位移,更可笑的。對于 64 bit 寄存器最多的位移數也是 31(見上面的鏈接)。這你能懂???究竟是我們的智商有問題,還是 Intel 的智商有問題?!

看下圖:


PS:糾正一下,上面這個舉例是錯誤的(是我看錯了),Intel 并沒有實現?PSRAQ。上面這個是 PSRAD 的。是針對 DWORD 的。而不是 QWORD,所以他這么實現是正確的,這里并沒有問題。


這個問題,在另外一個著名的帖子里也有提到:

千分求匯編優化:UInt96x96To192(...)


到眼下為止,都未實現 PSRAQ 指令。


. <END> .





本文轉自mfrbuaa博客園博客,原文鏈接:http://www.cnblogs.com/mfrbuaa/p/5365498.html,如需轉載請自行聯系原作者?

總結

以上是生活随笔為你收集整理的Intel大坑之中的一个:丢失的SSE2 128bit/64bit 位移指令,马航MH370??的全部內容,希望文章能夠幫你解決所遇到的問題。

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