我需要使用 Neon Intrinsics (in aarch64),并使用函式引數中傳遞的陣列中的稍微修改的資料:
void scenario1(uint16x8_t* X) {
uint16x8_t arrayTest01[4] = {
{X[0][4],X[0][5],X[0][6],X[0][7], -X[0][0],-X[0][1],-X[0][2],-X[0][3]},
{X[1][4],X[1][5],X[1][6],X[1][7], -X[1][0],-X[1][1],-X[1][2],-X[1][3]},
{X[2][4],X[2][5],X[2][6],X[2][7], -X[2][0],-X[2][1],-X[2][2],-X[2][3]},
{X[3][4],X[3][5],X[3][6],X[3][7], -X[3][0],-X[3][1],-X[3][2],-X[3][3]}
};
uint16x8_t arrayTest02[4];
arrayTest02[0] = vextq_u16(X[0], vmulq_n_u16(X[0],-1),4);
arrayTest02[1] = vextq_u16(X[1], vmulq_n_u16(X[1],-1), 4);
arrayTest02[2] = vextq_u16(X[2], vmulq_n_u16(X[2],-1), 4);
arrayTest02[3] = vextq_u16(X[3], vmulq_n_u16(X[3],-1), 4);
// Rest of code which uses arrayTest01 and/or arrayTest02
}
這個想法是,兩者arrayTest01都是從函式arrayTest02外部的結構陣列填充的資料查找表。和中scenario1的向量都是半正半負模 65536。arrayTest01arrayTest02
- 如果我使用
arrayTest01,那么 asm 代碼會執行一些 AND 和否定,但我不確定在使用 -O3 編譯后是否會出現這種情況(很難使用 -O3 進行除錯并命中該斷點)。我不確定在初始化時是否每個元素都是從記憶體中單獨加載的。 - 該操作
vmulq_n_u16乘以 -1(產生-X[i]),并vextq_u16提取 的上半部分X[i]和下半部分-X[i]。 - 操作
vmulq_n_u16和vextq_u16應該在一個周期內執行,因為它們是 SIMD,但仍然不確定它們最終是比初始化快還是慢。
我擔心的是兩者arrayTest01都會arrayTest02有數千個條目并且scenario1會被多次呼叫,所以我可以節省的任何執行時間/周期數都會有很大幫助。
問題
初始化陣列 (
arrayTest01) 中的元素是否分別從記憶體中加載?如果是這樣,那么 SIMD 操作會更快嗎?
一般來說,哪個會產生更快的執行時間?初始化陣列?或使用 SIMD 構造陣列?(同樣,最終的陣列將有數千個條目)
謝謝!
uj5u.com熱心網友回復:
首先,02 更快只是因為:
- 在這種情況下,自動矢量化對于 01 非常低效
- 在這種情況下,編譯器似乎對 02 相當溫和
然而,兩者都是次優的。
這個怎么樣?
uint16x8_t arrayTest03[4];
int64x2x4_t temp, rslt;
temp = vld4q_s64((int64_t *)X);
rslt.val[0] = temp.val[1];
rslt.val[1] = vreinterpretq_s64_s16(vnegq_s16(vreinterpretq_s16_s64(temp.val[0])));
rslt.val[2] = temp.val[3];
rslt.val[3] = vreinterpretq_s64_s16(vnegq_s16(vreinterpretq_s16_s64(temp.val[2])));
vst4q_s64((int64_t *)arrayTest03, rslt);
總共六個指令。
你應該跳出框框思考。不要拘泥于 C 中的資料型別和短代碼。
特別是,您應該明確地了解記憶體加載和存盤。你永遠不知道編譯器會產生什么樣的混亂。
順便說一句,所有陣列都應該對齊到 64 位元組以獲得最佳性能。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/520286.html
標籤:数组C手臂初始化氖
