swift - 在不同形状的金属纹理之间复制数据
问题描述
我正在将两个训练有素的 Keras 模型转换为金属性能着色器。我必须重塑第一个图的输出并将其用作第二个图的输入。第一个图的输出是一个具有“形状”(1,1,8192) 的 MPSImage,第二个图的输入是一个“形状”(4,4,512) 的 MPSImage。
我将 graph1 的输出 image.texture 转换为 float16 数组,并将其传递给以下函数以将数据复制到“midImage”,即 4x4x512 MPSImage:
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 切片属性。谢谢!
解决方案
金属二维纹理数组几乎总是以某种莫顿或“Z”顺序存储。当然 MPS 总是以这种方式分配它们,尽管我认为在 MacOS 上可能有一种方法可以制作线性 2D 纹理数组并在其周围包裹 MPSImage。因此,如果不小心,直接访问 2d 纹理数组后备存储将导致悲伤和混乱。
正确的做法是编写一个简单的 Metal 拷贝内核。这为您提供了存储顺序独立性,您不必等待命令缓冲区完成即可执行操作。
Radar 中的功能请求也可能是有保证的。另请查看最新的 macOS / iOS 种子,看看 Apple 最近是否为您添加了重塑过滤器。
推荐阅读
- c++ - C ++无法将基类“this”指针分配给基类构造函数中的派生类对象
- node.js - 如何解决 $PATH 中找不到 docker-entrypoint.sh 可执行文件:未知?
- tensorflow - TensorFlow 2 中的 Group Conv
- php - Laravel 8 使用 Guards Rest Password 的多重身份验证问题
- cmake - 找不到 Protobuf(缺少:Protobuf_INCLUDE_DIR)
- macos - MacOS:在 macOS 上找不到 .ivy2 文件夹
- gradle - 未解决的参考:pluginManagement
- react-native - AsyncStorage 保存多个项目
- javascript - 如何将数据表(对象)从javascript文件传递到节点js
- react-native - react native - 无法对未安装的组件执行 React 状态更新