end*_*vid 1 arrays ios swift metal
我在大阵列(图像)上做循环,通过仪器我发现主要的瓶颈是Array.subscript.nativePinningMutableAddressor,所以我做了这个单元测试来比较,
// average: 0.461 seconds (iPhone6 iOS 10.2) ~5.8 times slower than native arrays
func testArrayPerformance() {
self.measure {
var array = [Float](repeating: 1, count: 2048 * 2048)
for i in 0..<array.count {
array[(i+1)%array.count] = Float(i)
}
}
}
// average: 0.079 seconds
func testNativeArrayPerformance() {
self.measure {
let count = 2048 * 2048
let array = UnsafeMutablePointer<Float>.allocate(capacity: count)
for i in 0..<count {
array[(i+1)%count] = Float(i)
}
array.deallocate(capacity: count)
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,本机数组要快得多.还有其他方法可以更快地访问阵列吗?"不安全"听起来并不"安全",但在这种情况下你会做些什么呢?是否有其他类型的数组包装本机?
有关更复杂的示例,您可以看到本文中的注释:使用带符号距离字段在Metal中呈现文本 我在Swift中重新实现了该示例,并且原始实现需要52秒才能启动,https:// github .COM/endavid/VidEngine /树/ textprimitive失效
切换到本机阵列后,我下降到10秒,https://github.com/endavid/VidEngine/tree/fontatlas-array-optimization
在Xcode 8.3.3上测试过.
Edit1:此测试的时间是在Debug配置中,但是Signed Distance Fields示例的时间是Release配置.感谢评论中单元测试的微优化(计数,初始化),但在现实世界中,这些可以忽略不计,内存缓冲解决方案在iOS上仍然快5倍.
Edit2:以下是签名距离字段示例中最昂贵函数的时序(iPhone6上的Instruments会话),
Edit3:除了性能问题,我使用Swift数组时遇到了严重的内存问题.NSKeyedArchiver会耗尽内存并导致应用崩溃.我不得不使用字节缓冲区,并将其存储在一个NSData.参考.commit:https://github.com/endavid/VidEngine/commit/6c1822523a2b18759f294def3188755eaaf98b41
所以我想我的问题的答案是:对于大数字数据数组(例如图像),最好使用内存缓冲区.
简单地count将速度从0.2s 缓存到0.14s,这是基于指针的代码所用时间的两倍.考虑到基于数组的代码对所有元素进行预初始化,这是完全可以预料到的1.
基线:
缓存之后count: