我需要访问指向容器内存的指针,例如Accelerate和BLAS操作.
我想知道ArraySlice的指针是指向切片的第一个元素,还是指向其基数的第一个元素.
当我尝试测试UnsafePointer< Int>(array)== UnsafePointer< Int>(array [1 … 2])时,看起来Swift不允许从ArraySlices构建指针(或者我只是错误地做了).
我正在寻找关于哪种方式最“Swift-y”的建议?
我理解在切片数组时,后面的说法是正确的:
let array = [1, 2, 3] array[1] == array[1...2][1]
和
array[1...2][0] != 2 # index out of bounds error
换句话说,始终相对于基本数组执行索引.
这表明:我们应该返回一个指向基地第一个元素的指针.因为切片是相对于它们的基础.
但是,通过切片迭代(显然)只考虑该切片的元素:
for i in array[1..2] # i takes on 2 followed by 3
这表明:我们应该返回一个指向切片第一个元素的指针.因为切片有自己的起点.
如果我的用户想要在BLAS操作中对切片进行操作,那么期望直观:
mmul(matrix1[1...2, 0...1].pointer, matrix2[4...5, 0...1].pointer)
指向切片的第一个元素,但我不知道这是否是Swift ArraySlice做事的方式.
我的问题:容器切片对象的指针应该指向切片的第一个元素,还是基本容器的第一个元素.
此操作不安全:UnsafePointer<Int>(array)
你的意思是:
array.withUnsafeBufferPointer { ... }
这也适用于您的类型,并且是您应该用于与BLAS和Accelerate互操作的模式.你不应该尝试使用指针方法IMO.
在您实际访问指针时,即使在同一行代码中发生这种情况,也无法保证数组将继续存在. ARC可以自由地迅速摧毁那个记忆.
UnsafeBufferPointer实际上是一个非常好的类型,它已经被承诺是连续的并且它表现为一个集合.
我的建议是在内部管理你自己的内存,可能是使用ManagedBuffer,但也许只是你自己分配和销毁的UnsafeMutablePointer.管理数据布局以使其与Accelerate兼容非常重要.您不需要Array< Array< UInt8>>.这将增加太多的结构.您需要在良好的’C方式(行*宽度列等)中索引的字节blob.您可能不希望切片直接返回指针.您的mmul函数可能需要特殊的逻辑来理解如何通过最少的复制从片中拉出所需的片段,以便它可以与vDSP_mmul一起使用. “通用”和“加速”很少一起走.
例如,考虑到这个:
mmul(matrix1[1...2, 0...1].pointer, matrix2[4...5, 0...1].pointer)
(显然我假设你的真实矩阵要大得多;这种矩阵发送到vDSP没有多大意义.)
你将不得不在这里编写自己的mmul,因为这个内存没有正确布局.所以你不妨传递切片.然后你会做类似的事情(完全未经测试,未编译,我确信语法错误):
mmul(m1: MatrixSlice, m2: MatrixSlice) -> Matrix { var s1 = UnsafeMutablePointer<Float>.alloc(m1.rows * m1.columns) // use vDSP_vgathr to copy each sliced row out of m1 into s1 var s2 = UnsafeMutablePointer<Float>.alloc(m2.rows * m2.columns) // use vDSP_vgathr to copy each sliced row out of m2 into s2 var result = UnsafeMutablePointer<Float>.alloc(m1.rows * m2.columns) vDSP_mmul(s1, 1, s2, 1, result, 1, m1.rows, m2.columns, m1.columns) s1.destroy() s2.destroy() // This will need to call result.move() or moveInitializeFrom or something return Matrix(result) }
我只是扔掉了东西,但这可能是你想要的那种结构.
对于关于是否通常由Swift传递指向容器或数据的指针的基本问题,对于Array而言,答案很可能是“神奇”而没有其他人.将一个数组传递给需要指针的东西会神奇地(由编译器而不是stdlib)传递一个指向存储器的指针.没有其他类型获得这种魔力.甚至ContiguousArray都没有获得这种魔力.如果你将一个ContiguousArray传递给想要指针的东西,你会将指针传递给容器(如果它是可变的,那么破坏容器;真实的故事,讨厌那个…)