簡體   English   中英

我可以使用SIMD對存儲桶進行排序/分類嗎?

[英]Can I use SIMD to bucket sort / categorize?

我對SIMD感到好奇,想知道它是否可以處理此用例。

假設我有一個2048個整數的數組,例如[0x018A,0x004B,0x01C0、0x0234、0x0098、0x0343、0x0222、0x0301、0x0398、0x0087、0x0167、0x0389、0x03F2、0x0034、0x0345,...]

請注意它們如何以0x00、0x01、0x02或0x03開頭。 我想將它們分成4個數組:

  • 以0x00開頭的所有整數之一
  • 所有以0x01開頭的整數之一
  • 以0x02開頭的所有整數之一
  • 以0x03開頭的所有整數之一

我想我會有這樣的代碼:

int main() {
   uint16_t in[2048] = ...;

   // 4 arrays, one for each category
   uint16_t out[4][2048];

   // Pointers to the next available slot in each of the arrays
   uint16_t *nextOut[4] = { out[0], out[1], out[2], out[3] };

   for (uint16_t *nextIn = in; nextIn < 2048; nextIn += 4) {

       (*** magic simd instructions here ***)

       // Equivalent non-simd code:
       uint16_t categories[4];
       for (int i = 0; i < 4; i++) {
           categories[i] = nextIn[i] & 0xFF00;
       }
       for (int i = 0; i < 4; i++) {
           uint16_t category = categories[i];
           *nextOut[category] = nextIn[i];
           nextOut[category]++;
       }
   }
   // Now I have my categoried arrays!
}

我以為我的第一個內部循環不需要SIMD,它可以只是(x & 0xFF00FF00FF00FF00)指令,但是我想知道是否可以將第二個內部循環轉換為SIMD指令。

我正在執行的此“分類”操作是否有任何SIMD指令?

“插入”指令似乎有些許前途,但是我有點綠了,無法理解https://software.intel.com/zh-cn/node/695331上的描述。

如果沒有,有什么差事嗎?

謝謝!

您可以使用SIMD做到這一點,但是它的速度將取決於您可用的指令集的確切程度以及實現的精明程度。

一種方法是采用數組並將其“過濾”以分離出屬於不同存儲桶的元素。 例如,從數組中獲取32個字節,該數組將包含16個16位元素。 使用一些cmpgt指令獲取掩碼,該掩碼確定每個元素屬於00 + 01存儲桶還是02 + 03存儲桶。 然后使用某種“壓縮”或“過濾”操作將所有被屏蔽的元素連續移動到寄存器的一端,然后對未屏蔽的元素進行相同的移動。

然后再重復一次,從01選出00 ,從03選出02

使用AVX2,您可以從這個問題開始,以啟發“壓縮”操作。 使用AVX512,您可以使用vcompress指令來提供幫助:它可以完全執行此操作,但僅以32位或64位粒度執行,因此您至少需要對每個向量進行兩次操作。

您也可以嘗試一種垂直方法,先加載N個向量,然后在它們之間交換,以便第0個向量具有最小的元素,依此類推。此時,您可以對壓縮階段使用更優化的算法(例如,如果您在垂直方向上對足夠多的向量進行了排序,則末端的向量可能完全以0x00等開頭)。

最后,您還可以考慮在源頭或作為預處理步驟來不同地組織數據:從有效載荷字節中分離出始終為0-3的“類別”字節。 許多處理步驟只需要在一個或另一個上執行,因此您可以通過將它們分開來提高效率。 例如,您可以對所有類別的32個字節進行比較操作,然后對32個有效負載字節進行壓縮操作(至少在每個類別都是唯一的最后一步中)。

這將導致字節元素數組,而不是16位元素數組,其中“類別”字節是隱式的。 您已將數據大小減少了一半,這可能會加快您將來對數據進行的其他處理。

如果無法生成這種格式的源數據,則可以在將有效負載放入正確的存儲桶中時使用存儲桶作為刪除標記字節的機會,因此輸出為uint8_t out[4][2048]; 如果按照注釋中的說明使用pshufb字節混洗來進行SIMD左包裝,則可以選擇一種混洗控制向量,該控制向量僅將有效載荷字節pshufb到下半部分。

(直到AVX512BW,x86 SIMD都沒有任何可變控制字改組,只有字節或dword,因此您已經需要一個字節改組,它可以像將有效載荷字節打包到底部一樣輕松地將有效載荷與標記分開。 )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM