2016-08-31 72 views
0

我在某些C代碼中使用AVX2指令。從基於源的索引轉換爲基於目標的索引

VPERMD指令採用兩個8整數矢量aidx併產生第三個,dst,通過基於idx置換a。這似乎相當於dst[i] = a[idx[i]] for i in 0..7。我打電話給這個來源,因爲這個舉動是根據來源索引的。

但是,我有我的計算指數以目的地爲基礎的形式。這對設置數組很自然,相當於dst[idx[i]] = a[i] for i in 0..7

如何將基於源代碼的表單轉換爲基於目標的表單?一個例子測試用例是:

{2 1 0 5 3 4 6 7} source-based form. 
{2 1 0 4 5 3 6 7} destination-based equivalent 

對於這種轉換,我住在ymm寄存器,這樣就意味着基於目標的解決方案不起作用。即使我分別插入每一個,因爲它只能在不變的索引上運行,所以不能只設置它們。

+1

這只是經典的「排列反轉」,'dst [src [i]] = i' – harold

+0

沒錯。但是你的代碼需要能夠以基於目標的方式進行設置。由於我在AVX2寄存器中操作。我不能那樣做。我的工作C代碼幾乎完全按照您的說法來完成,但是我需要能夠轉換索引而無需執行基於目標的排列,就像您所建議的那樣。 – eyepatch

+0

對於0..7中的i,你的'a [i] = a [idx [i]]沒有正確描述VPERMD的操作,因爲它意味着'a'的改變會反饋到'a [idx [我]]'爲了以後的元素。例如除非'idx [0] = 0',原始的'a [0]'將會被立即銷燬。我認爲你的例子在編輯之後仍然很正常,以糾正這個錯誤(或者假設整個行爲都是這種行爲)。 –

回答

2

我想你是隱含地說,你不能修改你的代碼來首先計算基於源碼的索引?除了採用基於dst的索引的AVX512分散指令外,我無法想象您可以使用x86 SIMD執行任何操作。

存儲到內存,反轉和重新加載矢量可能實際上是最好的。 (或者直接傳遞到整數寄存器,而不是通過內存,也許在vextracti128/packusdw之後,所以你只需要兩個從向量到整數寄存器的64位傳輸:movq和pextrq)。

但無論如何,然後使用它們作爲索引將計數器存儲到內存中的數組中,然後將其作爲向量重新加載。這仍然是緩慢和醜陋的,並且包括存儲轉發失敗延遲。因此,您可能需要更改索引生成代碼以生成基於源碼的隨機向量。