Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 来自ArraySlice的快速指针_Swift - Fatal编程技术网

Swift 来自ArraySlice的快速指针

Swift 来自ArraySlice的快速指针,swift,Swift,我试图确定创建自己的连续内存容器的“Swift-y”方式(在我的特定情况下,我正在构建n维数组)。我希望我的容器在功能和可用性方面尽可能接近Swift的内置阵列 我需要访问指向容器内存的指针,以便进行加速和BLAS操作 我想知道ArraySlice的指针是指向切片的第一个元素,还是指向其基的第一个元素 当我尝试测试UnsafePointer(array)==UnsafePointer(array[1…2])时,Swift似乎不允许从ArraySlices构造指针(或者我做得不正确) 我在寻求关

我试图确定创建自己的连续内存容器的“Swift-y”方式(在我的特定情况下,我正在构建n维数组)。我希望我的容器在功能和可用性方面尽可能接近Swift的内置阵列


我需要访问指向容器内存的指针,以便进行加速和BLAS操作

我想知道ArraySlice的指针是指向切片的第一个元素,还是指向其基的第一个元素

当我尝试测试
UnsafePointer(array)==UnsafePointer(array[1…2])
时,Swift似乎不允许从ArraySlices构造指针(或者我做得不正确)

我在寻求关于哪种方式最“快捷”的建议


我知道在切片阵列时,以下情况是正确的:

let array = [1, 2, 3]
array[1] == array[1...2][1]

换句话说,索引总是相对于基数组执行

这表明:我们应该返回一个指向基的第一个元素的指针。因为切片是相对于其底部的


但是,通过切片的迭代(显然)只考虑该切片的元素:

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)
指向slice的第一个元素,但我不知道这是否是Swift ArraySlice的工作方式



我的问题:容器切片对象的指针应该指向切片的第一个元素,还是指向基本容器的第一个元素

此操作不安全:

UnsafePointer<Int>(array)
这也适用于您的类型,并且是您应该用来与BLAS进行互操作和加速的模式。您不应该尝试使用
指针
方法

无法保证在实际访问指针时,
array
将继续存在,即使这发生在同一行代码中。ARC可以自由地以惊人的速度破坏内存

UnsafeBufferPointer
实际上是一种非常好的类型,因为它已经承诺是连续的,并且它的行为就像一个集合

我的建议是在内部管理您自己的内存,可能使用
ManagedBuffer
,但可能只使用
unsafemeutablepointer
,您可以
alloc
销毁自己。管理数据的布局以使其与Accelerate兼容非常重要。您不需要
数组
。这会增加太多的结构。您需要一个字节块,以良好的ol'C方式(行*宽+列等)索引到该字节块中。您可能根本不希望切片直接返回指针。您的
mmul
函数可能需要特殊的逻辑来理解如何以最少的复制从片中取出所需的片段,以便与
vDSP\u mmul
一起工作。“通用”和“加速”很少同时出现

例如,考虑到这一点:

mmul(matrix1[1...2, 0...1].pointer, matrix2[4...5, 0...1].pointer)
(显然,我假设您的真实矩阵非常大;这种矩阵发送到vDSP没有多大意义。)

显然,由于内存布局不正确,您必须在此处编写自己的
mmul
。所以你最好把切片递给我。然后你会做一些类似的事情(完全未经测试,未编译,我确信语法是错误的):

mmul(m1:MatrixSlice,m2:MatrixSlice)->矩阵{
var s1=UnsafeMutablePointer.alloc(m1.rows*m1.columns)
//使用vDSP_vgathr将m1中的每个切片行复制到s1中
var s2=UnsafeMutablePointer.alloc(m2.rows*m2.columns)
//使用vDSP_vgathr将m2中的每个切片行复制到s2中
var result=unsafemeutablepointer.alloc(m1.rows*m2.columns)
vDSP_mmul(s1,1,s2,1,result,1,m1.行,m2.列,m1.列)
s1.销毁()
s2.销毁()
//这将需要调用result.move()或moveInitializeFrom或其他函数
返回矩阵(结果)
}
我只是在这里扔东西,但这可能是你想要的结构


关于指向容器或数据的指针通常是由Swift传递的这一潜在问题,不幸的是,答案对于数组来说是“神奇的”,而对于其他任何人来说都不是。将数组传递给需要指针的对象将神奇地(由编译器而不是stdlib)将指针传递给数组的存储器。没有其他类型的人有这种魔力。即使是
ContiguousArray
也无法获得这种魔力。如果您将
连续数组
传递给需要指针的对象,您将把指针传递给容器(如果它是可变的,则会损坏容器;真实的故事,讨厌那个…)

一定程度上要感谢@RobNapier。我的问题的答案是:ArraySlice的指针应该指向切片的第一个元素

我验证这一点的方式很简单:

var array = [5,4,3,325,67,7,3]
array.withUnsafeBufferPointer{ $0 } != array[3...6].withUnsafeBufferPointer{ $0 } # true
  ^--- points to 5's address             ^--- points to 325's address
mmul(matrix1[1...2, 0...1].pointer, matrix2[4...5, 0...1].pointer)
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)
 }
var array = [5,4,3,325,67,7,3]
array.withUnsafeBufferPointer{ $0 } != array[3...6].withUnsafeBufferPointer{ $0 } # true
  ^--- points to 5's address             ^--- points to 325's address