我正在使用ARM NEON彙編器優化4D(128位)矩陣向量乘法。如何使用ARM NEON優化環形4D矩陣向量乘法?
如果我加載矩陣,並將向量導入NEON寄存器並對其進行轉換,我不會得到很好的性能提升,因爲切換到NEON寄存器要花費20個週期。此外,我重新加載每個乘法的矩陣,儘管它沒有改變。
有足夠的寄存器空間在一次更多的向量上執行轉換。這是提高性能。
但是...
我不知道如何快,如果我做遍歷所有頂點這一操作將是(增加指針)彙編內。但我在Neon彙編程序的開頭,雖然不知道如何做到這一點。有人能幫我一下嗎?
我想達到的目標:
- 載荷矩陣和第一矢量
- 店循環計數 「計數」 和..
- - LOOP_START -
- 執行乘加(做轉化)
- 寫入Q0至Vout
- 增加指針VIN和VOUT由4(128位)
- 加載vIn到q5。
- - LOOP_END -
現有循環的C-版本:
void TransformVertices(ESMatrix* m, GLfloat* vertices, GLfloat* normals, int count)
{
GLfloat* pVertex = vertices;
int i;
// iterate trough vertices only one at a time
for (i = 0; i < count ; i ++)
{
Matrix4Vector4Mul((float *)m, (float *)pVertex, (float *)pVertex);
pVertex += 4;
}
//LoadMatrix((const float*) m);
//// two at a time
//for (i = 0; i < count ; i += 2)
//{
// Matrix4Vector4Mul2((float *)m, (float *)pVertex, (float *)(pVertex + 4));
// pVertex += 8;
//}
}
繼只做一個轉型的NEON-版本代碼:
void Matrix4Vector4Mul (const float* m, const float* vIn, float* vOut)
{
asm volatile
(
"vldmia %1, {q1-q4 } \n\t"
"vldmia %2, {q5} \n\t"
"vmul.f32 q0, q1, d10[0] \n\t"
"vmla.f32 q0, q2, d10[1] \n\t"
"vmla.f32 q0, q3, d11[0] \n\t"
"vmla.f32 q0, q4, d11[1] \n\t"
"vstmia %0, {q0}"
: // no output
: "r" (vOut), "r" (m), "r" (vIn)
: "memory", "q0", "q1", "q2", "q3", "q4", "q5"
);
}
C-版本轉化:
void Matrix4Vector4Mul (const float* m, const float* vIn, float* vOut)
{
Vertex4D* v1 = (Vertex4D*)vIn;
Vertex4D vOut1;
Vertex4D* l0;
Vertex4D* l1;
Vertex4D* l2;
Vertex4D* l3;
// 4x4 Matrix with members m00 - m33
ESMatrix* m1 = (ESMatrix*)m;
l0 = (Vertex4D*)&m1->m00;
vOut1.x = l0->x * v1->x;
vOut1.y = l0->y * v1->x;
vOut1.z = l0->z * v1->x;
vOut1.w = l0->w * v1->x;
l1 = (Vertex4D*)&m1->m10;
vOut1.x += l1->x * v1->y;
vOut1.y += l1->y * v1->y;
vOut1.z += l1->z * v1->y;
vOut1.w += l1->w * v1->y;
l2 = (Vertex4D*)&m1->m20;
vOut1.x += l2->x * v1->z;
vOut1.y += l2->y * v1->z;
vOut1.z += l2->z * v1->z;
vOut1.w += l2->w * v1->z;
l3 = (Vertex4D*)&m1->m30;
vOut1.x += l3->x * v1->w;
vOut1.y += l3->y * v1->w;
vOut1.z += l3->z * v1->w;
vOut1.w += l3->w * v1->w;
*(vOut) = vOut1.x;
*(vOut + 1) = vOut1.y;
*(vOut + 2) = vOut1.z;
*(vOut + 3) = vOut1.w;
}
性能:(變換> 90 000個頂點|安卓4.0.4 SGS II)
C-Version: 190 FPS
NEON-Version: 162 FPS (.. slower -.-)
--- LOAD Matrix only ONCE (seperate ASM) and then perform two V's at a time ---
NEON-Version: 217 FPS (+ 33 % NEON | + 14 % C-Code)
在簡單的C中提供循環,人們會更容易。 – auselen
哦,是啊..猜你是對的! – oc1d
也提供Matrix4Vector4Mul,實際上就是讓它們成爲一個循環,就像你用普通的c書寫它一樣。 – auselen