這種循環很難使用SIMD指令進行優化。在大多數SIMD指令集中,不僅沒有一種簡單的方法來進行這種索引讀取(「聚集」)或寫入(「分散」),即使存在,這個特定的循環仍然存在您可能遇到的問題兩個值在一個SIMD寄存器中映射到相同的id
,例如當
id[0] == 0
id[1] == 1
id[2] == 2
id[3] == 0
在這種情況下
,明顯的方法(這裏的僞代碼)
x = gather(size, id[i]);
y = gather(sum, id[i]);
x += 1; // componentwise
y += value[i];
scatter(x, size, id[i]);
scatter(y, sum, id[i]);
不會工作!
你可以通過,如果有一個非常小的一些可能的情況下(例如,假設sum
和size
只有各3片)通過只是在做蠻力相比,但並沒有真正規模。不使用SIMD稍快得到這個
一種方式是通過破壞指令之間的依賴關係使用展開了一下:
int size[10] = { 0 }, size2[10] = { 0 };
int sum[10] = { 0 }, sum2[10] = { 0 };
for (int i = 0; i < N/2; i++) {
int id0 = id[i*2+0], id1 = id[i*2+1];
++size[id0];
++size2[id1];
sum[id0] += value[i*2+0];
sum2[id1] += value[i*2+1];
}
// if N was odd, process last element
if (N & 1) {
++size[id[N]];
sum[id[N]] += value[N];
}
// add partial sums together
for (int i = 0; i < 10; i++) {
size[i] += size2[i];
sum[i] += sum2[i];
}
這是否有助於與否雖然取決於目標CPU上。
只是爲了確保,在重新al代碼是`size`和`sum`自動變量在這裏?如果它們不是(例如,如果它們是通過指針或引用傳入到實際例程中的話),那麼可能會由於sum和value之間出現混疊的可能性而導致人爲的低效率和/大小`和`id`。 – 2010-12-04 20:28:01
這裏將並行化算作一個優化嗎?即將數組分割成多個子數組,然後將每個子數組傳遞給一個單獨的線程進行迭代,然後在最後組合結果。對於足夠大的陣列,至少在多核機器上可以提供很好的加速。 – 2010-12-04 20:32:02
是的,大小和總和是這樣的變量。分區聽起來像是一個好主意,我會嘗試memcpy將它們分解成四個宿區並且並行運行它們。 – Dmi 2010-12-04 20:35:10