我正在将两个训练有素的Keras模型转换为Metal Performance Shaders。我必须重塑第一张图的输出并将其用作第二张图的输入。第一个图形的输出是具有“形状”(1,1,8192)的MPSImage,第二个图形的输入是具有“形状”(4,4,512)的MPSImage。
我将graph1的输出image.texture转换为float16数组,并将其传递给以下函数,以将数据复制到4x4x512 MPSImage“ midImage”中:
func reshapeTexture(imageArray:[Float16]) -> MPSImage{
let image = imageArray
image.withUnsafeBufferPointer { ptr in
let width = midImage.texture.width
let height = midImage.texture.height
for slice in 0..<128{
for w in 0..<width{
for h in 0..<height{
let region = MTLRegion(origin: MTLOriginMake(w, h, 0),
size: MTLSizeMake(1, 1, 1))
midImage.texture.replace(region: region, mipmapLevel: 0, slice: slice, withBytes: ptr.baseAddress!.advanced(by: ((slice * 4 * width * height) + ((w + h) * 4)), bytesPerRow: MemoryLayout<Float16>.stride * 4, bytesPerImage: 0)
}
}
}
}
return midImage
}
当我将midImage传递给graph2时,图形的输出是一个正方形,其杂乱的噪声为3/4,右下角为1/4黑色。我想我不了解有关MPSImage slice属性用于存储额外通道的信息。谢谢!
答案 0 :(得分:0)
金属2d纹理阵列几乎总是以某种Morton或“ Z”顺序存储。当然,MPS总是以这种方式分配它们,尽管我认为在MacOS上可能有一种方法可以制作线性2D纹理数组并将MPSImage包裹在其周围。因此,如果没有适当的照顾,直接访问2d纹理阵列后备存储将导致悲伤和困惑。
正确的方法是编写一个简单的Metal复制内核。这样可以使存储顺序独立,并且您无需等待命令缓冲区完成就可以执行操作。
也可能需要Radar中的功能请求。还请查看最新的macOS / iOS种子,以了解Apple最近是否为您添加了变形过滤器。