我写了这个非常天真的NEON实现,从RGBA转换为RGB.它有效,但我想知道我还能做些什么来进一步提高性能.
我尝试使用预取大小,然后再展开循环,但性能没有太大变化.顺便说一句,在预取的尺寸方面,是否有任何经验法则?我在网上找不到任何有用的东西.此外,在"ARMv8指令集概述"中,我看到还有一个存储预取,这有用吗?
目前我正在大约1.7ms转换iPhone5s上的1280x720图像.
// unsigned int * rgba2rgb_neon(unsigned int * pDst, unsigned int * pSrc, unsigned int count); _rgba2rgb_neon: cmp w2, #0x7 b.gt loop mov w0, #0 ret loop: prfm pldl1strm, [w1, #64] ld4.8b {v0, v1, v2, v3}, [w1], #32 ld4.8b {v4, v5, v6, v7}, [w1], #32 prfm pldl1strm, [w1, #64] st3.8b {v0, v1, v2}, [w0], #24 st3.8b {v4, v5, v6}, [w0], #24 subs w2, w2, #16 b.gt loop done: ret
Stephen Cano.. 5
首先(因为我假设您的目标是iOS),vImage(Accelerate.framework的一部分)为您提供此转换,如vImageConvert_RGBA8888toRGB888.这具有可在所有iOS和OS X系统上使用的优点,因此您无需为arm64,armv7s,armv7,i386,x86_64编写单独的实现.
现在,可能是你自己编写这个转换作为练习,而不是因为你根本不知道一个已经可用.在这种情况下:
避免使用ld[34]
或st[34]
.它们很方便但通常比使用ld1
和置换慢.
对于像这样的完全常规的数据访问模式,不需要手动预取.
加载四个16b RGBA矢量ld1.16b
,用三个tbl.16b
指令从中提取三个16b RGB矢量,然后存储它们st1.16b
或者,尝试使用非临时加载和存储(ldnp
/ stnp
),因为您的图像大小太大而无法放入缓存中.
最后,回答你的问题:存储的预取提示主要是有用的,因为某些实现可能会导致部分行写入错过高速缓存的显着停顿.对于任何错过缓存的写入,特别简单的实现可能会有停顿.
首先(因为我假设您的目标是iOS),vImage(Accelerate.framework的一部分)为您提供此转换,如vImageConvert_RGBA8888toRGB888.这具有可在所有iOS和OS X系统上使用的优点,因此您无需为arm64,armv7s,armv7,i386,x86_64编写单独的实现.
现在,可能是你自己编写这个转换作为练习,而不是因为你根本不知道一个已经可用.在这种情况下:
避免使用ld[34]
或st[34]
.它们很方便但通常比使用ld1
和置换慢.
对于像这样的完全常规的数据访问模式,不需要手动预取.
加载四个16b RGBA矢量ld1.16b
,用三个tbl.16b
指令从中提取三个16b RGB矢量,然后存储它们st1.16b
或者,尝试使用非临时加载和存储(ldnp
/ stnp
),因为您的图像大小太大而无法放入缓存中.
最后,回答你的问题:存储的预取提示主要是有用的,因为某些实现可能会导致部分行写入错过高速缓存的显着停顿.对于任何错过缓存的写入,特别简单的实现可能会有停顿.