2012-12-21 64 views
6

我使用2個無符號短褲的緊湊結構來表示開始和結束位置。
我需要能夠快速確定是否有任何長度(開始與結束之間的差異)超過閾值的對象Range向量化涉及短褲的條件

我將擁有大量的物體,每個物體都有自己的Range數組,因此跟蹤哪些物體在列表中的閾值以上是不可行的。這段代碼也會經常運行(每個陣列每秒多次),所以它需要高效。

struct Range 
{ 
unsigned short start; 
unsigned short end; 
} 

我將始終有一個大小爲2^n的Range數組。雖然我想盡快放棄一旦我發現超過門檻,我敢肯定它將所有在一起,並在最後檢查會更快...假設我可以矢量化循環。雖然如果我可以對每個向量的結果塊做一個if語句,那將是非常好的。

size_t rangecount = 1 << resolution; 
Range* ranges = new Range[rangecount]; 

... 

bool result = false; 
for (size_t i = 0; i < ranges; ++i) 
{ 
result |= (range[i].end - range[i].start) > 4; 
} 

毫不奇怪,自動矢量化器給出了1202錯誤,因爲我的數據類型不是32位或64位寬。我真的不想加倍我的數據大小,並使每個字段爲unsigned int。所以我猜測這種自動矢量化方法已經不適用了。

是否有矢量指令可以處理16位變量?如果有的話,我如何在C++中使用它們來矢量化我的循環?

+0

你需要的範圍值存儲在一個數組?爲什麼不將它們存儲在另一個可以使查找速度更快的數據結構中? – loganfsmyth

+0

_so跟蹤哪個Range對象超出列表中的閾值或something_是不可行的。如果你想要做的是確定你是否有範圍破壞規則,那麼跟蹤它。你不必跟蹤每個對象來做到這一點。 –

+0

你多久使用'end'?切換到「(start,size)」表示而不是「(start,end)'是否可行?你當然需要在每次使用時計算'end',但是如果'end'和'size'的相對用法很低,那麼最終可能是一個贏...... – twalberg

回答

1

您想知道任何值是否大於4?

是的,這裏有SIMD指令。不幸的是,自動矢量化無法處理這種情況。這裏的一個量化算法:

diff_v = end_v - start_v; // _mm_hsub_epi16 
floor_v = max(4_v, diff_v); // _mm_max_epi16 
if (floor_v != 4_v) return true; // wide scalar comparison 

使用_mm_sub_epi16與陣列的結構或與_mm_hsub_epi16結構的陣列。

其實因爲start首先存儲在內存中,你將致力於start_v - end_v,所以使用_mm_min_epi16-4向量。

每個SSE3指令一次執行8次比較。儘早返回而不是循環將仍然是最快的。但是,多循環展開循環可能會爲您提供額外的速度(將第一組結果傳遞到打包的最小/最大函數中進行組合)。

所以你最終(大約):

most_negative = threshold = _mm_set_epi64(0xFCFCFCFCFCFCFCFC); // vectorized -4 

loop: 
    a = load from range; 
    b = load from range; 
    diff = _mm_hsub_epi16(a, b); 
    most_negative = _mm_min_epi16(most_negative, diff); 

    // unroll by repeating the above four instructions 4 times or so 
    if (most_negative != threshold) return true; 
repeat loop 
+0

對於自動矢量化程序無法做到的事情,那看起來很簡單! – user173342

+0

@ user173342:處理具有兩個成員的交錯數組是特例,而自動矢量化器可能還沒有準備好。 –