我正在尝试使用NEON(ios,> arm7)在平截头体中优化aabb盒,而我只是对基准测试结果感到困惑。
NEON版本(使用NEON的GLKVector4DotProduct):
FORCE_INLINE bool box_in_view1(const GLKVector4& min, const GLKVector4& max)
{
#define test_plane(i) { \
const GLKVector4& fp = frustum_plane[i]; \
if (GLKVector4DotProduct(fp, GLKVector4Make(min.x, min.y, min.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(max.x, min.y, min.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(min.x, max.y, min.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(max.x, max.y, min.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(min.x, min.y, max.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(max.x, min.y, max.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(min.x, max.y, max.z, 1.0f)) <= 0.0f && \
GLKVector4DotProduct(fp, GLKVector4Make(max.x, max.y, max.z, 1.0f)) <= 0.0f) { \
return false; \
} \
}
test_plane(0);
test_plane(1);
test_plane(2);
test_plane(3);
test_plane(4);
test_plane(5);
return true;
}
没有NEON:
FORCE_INLINE bool box_in_view2(const GLKVector4& min, const GLKVector4& max)
{
#define test_plane(i) { \
const GLKVector4& fp = frustum_plane[i]; \
float negw = -fp.w; \
if (fp.x * min.x + fp.y * min.y + fp.z * min.z <= negw && \
fp.x * max.x + fp.y * min.y + fp.z * min.z <= negw && \
fp.x * min.x + fp.y * max.y + fp.z * min.z <= negw && \
fp.x * max.x + fp.y * max.y + fp.z * min.z <= negw && \
fp.x * min.x + fp.y * min.y + fp.z * max.z <= negw && \
fp.x * max.x + fp.y * min.y + fp.z * max.z <= negw && \
fp.x * min.x + fp.y * max.y + fp.z * max.z <= negw && \
fp.x * max.x + fp.y * max.y + fp.z * max.z <= negw) { \
return false; \
} \
}
test_plane(0);
test_plane(1);
test_plane(2);
test_plane(3);
test_plane(4);
test_plane(5);
return true;
}
在简单的基准时间中是:
box_in_view1: 1.9704s
box_in_view2: 0.0013s
使用静态aabb盒和静态平截头体进行10000万次测试(立方体在内部,所以所有测试都返回true)。
在ipad3上测试,ios7,编译器选择标志:-Ofast -ffast-math
我确信GLKVector4DotProduct()确实在 ARM_NEON 路径中使用了NEON instrics。任何解释为什么NEON会导致这么慢?为什么?
答案 0 :(得分:1)
以下是完全优化版本,必须比现有版本快得多:
/*
fanicBoxInView
Copyright (C) 2014 Jake Lee
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// int fanicBoxInView(void *pMin, void *pMax, void *pFp, unsigned int count);
// assert : count >= 4
.text
.arm
.global fanicBoxInView
pMin .req r0
pMax .req r1
pFp .req r2
count .req r3
.align 5
.func
fanicBoxInView:
vld1.32 {q12}, [pMin]
vld1.32 {q13}, [pMax]
subs count, count, #4
vmov.i32 q14, #0
vmov.i32 q15, #0
bxmi lr
vpush {q6-q7}
vzip.32 q12, q13
1:
vld1.32 {q0,q1}, [pFp]!
vld1.32 {q2,q3}, [pFp]!
pld [pFp, #64*3]
subs count, count, #4
vdup.32 d20, d1[1]
vdup.32 d21, d3[1]
vdup.32 d22, d5[1]
vdup.32 d23, d7[1]
vmul.f32 d12, d25, d0[1]
vmul.f32 d13, d25, d2[1]
vmul.f32 d14, d25, d4[1]
vmul.f32 d15, d25, d6[1]
vneg.f32 q10, q10
vneg.f32 q11, q11
vmul.f32 d16, d26, d1[0]
vmul.f32 d17, d26, d3[0]
vmul.f32 d18, d26, d5[0]
vmul.f32 d19, d26, d7[0]
vmls.f32 d20, d24, d0[0]
vmls.f32 d21, d24, d2[0]
vmls.f32 d22, d24, d4[0]
vmls.f32 d23, d24, d6[0]
vrev64.32 q0, q6
vrev64.32 q1, q7
vadd.f32 q6, q6, q8
vadd.f32 q7, q7, q9
vadd.f32 q8, q8, q0
vadd.f32 q9, q9, q1
vrev64.32 q0, q6
vrev64.32 q1, q7
vrev64.32 q2, q8
vrev64.32 q3, q9
vcgt.f32 q6, q6, q10
vcgt.f32 q7, q7, q11
vcgt.f32 q8, q8, q10
vcgt.f32 q9, q9, q11
vcgt.f32 q0, q0, q10
vcgt.f32 q1, q1, q11
vcgt.f32 q2, q2, q10
vcgt.f32 q3, q3, q11
vorr q6, q7, q6
vorr q8, q9, q8
vorr q0, q1, q0
vorr q2, q3, q2
vorr q14, q6, q14
vorr q15, q8, q15
vorr q14, q14, q0
vorr q15, q15, q2
bpl 1b
cmp count, #-4
add pFp, pFp, count, lsl #2
bgt 1b
vorr q14, q15, q14
vpop {q6-q7}
vmov r0, r1, d28
vmov r2, r3, d29
orr r0, r1, r0
orr r2, r3, r2
orr r0, r2, r0
bx lr
.endfunc
.end
以上语法适用于Linaro GCC。您必须对XCode进行一些更改: How do I use the ARM assembler in XCode?
请注意,您必须断言(count> = 4);
另请注意,当(count%4 == 0);
时,代码运行效率最高玩得开心。
PS:我是一个专业优化器,具有“按需优化”的做法,而我的客户对我最近在此免费提供完全优化的代码的活动并不满意。因此,我不得不把它变成GPL。