我注意到了这一点
let a = [Float](repeating: 0, count: len)
花费的时间远远超过
let p = UnsafeMutablePointer<Float>.allocate(capacity: len)
但是,不安全的指针使用起来不太方便,因此可能需要创建一个Array<Float>
才能传递给其他代码。
let a = Array(UnsafeBufferPointer(start: p, count: len))
但是这样做绝对会杀死它,并且创建带有填充零的Array
更快。
有人知道如何更快地创建Array
并同时方便实际使用Array<Float>
吗?在我的项目上下文中,我可能可以在内部处理不安全的指针,并且仅在模块外部需要时才用Array
包装它。
快速测试本文中的所有答案:
let len = 10_000_000
benchmark(title: "array.create", num_trials: 10) {
let a = [Float](repeating: 0, count: len)
}
benchmark(title: "array.create faster", num_trials: 10) {
let p = UnsafeMutableBufferPointer<Float>.allocate(capacity: len)
}
benchmark(title: "Array.reserveCapacity ?", num_trials: 10) {
var a = [Float]()
a.reserveCapacity(len)
}
benchmark(title: "ContiguousArray ?", num_trials: 10) {
let a = ContiguousArray<Float>(repeating: 0, count: len)
}
benchmark(title: "ContiguousArray.reserveCapacity", num_trials: 10) {
var a = ContiguousArray<Float>()
a.reserveCapacity(len)
}
benchmark(title: "UnsafeMutableBufferPointer BaseMath", num_trials: 10) {
let p = UnsafeMutableBufferPointer<Float>(len) // Jeremy's BaseMath
print(p.count)
}
结果:(1000万浮动)
array.create:9.256毫秒
array.create更快:0.004毫秒
Array.reserveCapacity?:0.264毫秒
ContiguousArray吗?:10.154毫秒
ContiguousArray.reserveCapacity:3.251毫秒
UnsafeMutableBufferPointer BaseMath:0.049毫秒
我正在通过释放模式在iPhone模拟器上专门运行一个应用程序。我知道我可能应该在命令行/独立模式下执行此操作,但是由于我计划将其编写为应用程序的一部分,因此可能没问题。
对于我尝试做的事情,UnsafeMutableBufferPointer看起来很棒,但是您必须使用BaseMath及其所有一致性。如果您追求的是一般性或其他背景。请务必阅读所有内容,并确定哪一种适合您。
答案 0 :(得分:1)
如果需要性能,并且知道所需的大小,可以使用reserveCapacity(_:),这将为数组的内容预分配所需的内存。根据Apple文档:
如果要向数组中添加已知数量的元素,请使用此方法避免多次重新分配。此方法可确保数组具有唯一的,可变的,连续的存储,并至少为请求的元素数量分配了空间。
在具有桥接存储的阵列上调用reserveCapacity(_ :)方法会触发向连续存储的复制,即使现有存储有空间可以存储minimumCapacity元素。
出于性能原因,新分配的存储大小可能大于请求的容量。使用阵列的Capacity属性确定新存储的大小。
答案 1 :(得分:0)
这是最接近我想要的东西。有一个名为BaseMath的库(由Jeremy Howard开始),还有一个新的类,名为AlignedStorage和UnsafeMutableBufferPointer。它具有很多数学功能,而且非常快,因此可以减少使用数学算法时指针的管理。
但这还有待测试,这个项目是非常新的。我将保留此问题,以了解是否有人可以提出更好的建议。
注意:这是我正在做的事情中最快的。如果您确实需要一个好的结构值类型Array(和变体),请参阅其他答案。