我正在研究使用Swift和Metal在GPU上进行图像处理的macOS项目.上周,我收到了我的新款15英寸MacBook Pro(2016年末)并注意到我的代码有些奇怪:应该写入纹理的内核似乎没有这样做......
经过大量挖掘后,我发现问题与Metal(AMD Radeon Pro 455或Intel(R)HD Graphics 530)使用哪个GPU进行计算有关.
初始化MTLDeviceusing MTLCopyAllDevices()返回表示Radeon和Intel GPU的设备数组(同时MTLCreateSystemDefaultDevice()返回默认设备Radeon).在任何情况下,代码都可以像英特尔GPU一样工作,但Radeon GPU并非如此.
让我举个例子.
首先,这是一个简单的内核,它接受输入纹理并将其颜色复制到输出纹理:
kernel void passthrough(texture2d<uint, access::read> inTexture [[texture(0)]],
texture2d<uint, access::write> outTexture [[texture(1)]],
uint2 gid [[thread_position_in_grid]])
{
uint4 out = inTexture.read(gid);
outTexture.write(out, gid);
}
Run Code Online (Sandbox Code Playgroud)
我命令使用这个内核,我使用这段代码:
let devices = MTLCopyAllDevices()
for device in devices {
print(device.name!) // [0] -> "AMD Radeon Pro 455", [1] -> "Intel(R) HD Graphics 530"
}
let device = devices[0]
let library = device.newDefaultLibrary()
let commandQueue = device.makeCommandQueue()
let passthroughKernelFunction = …Run Code Online (Sandbox Code Playgroud) 我目前正在研究iOS中的图像处理应用程序的金属内核(在.metal文件中).我想要包含一些标准的C++库(例如或),但Xcode似乎不允许它(我在编译时遇到"找不到文件"错误.
以前有人遇到过这类问题吗?在不使用某些基本库的情况下,能够在金属中编写自定义内核似乎很荒谬,这让我觉得必须有答案.
在使用新的 Swift 并发工具时发现了这个问题。
这是设置:
class FailedDeinit {
init() {
print(#function, id)
task = Task {
await subscribe()
}
}
deinit {
print(#function, id)
}
func subscribe() async {
let stream = AsyncStream<Double> { _ in }
for await p in stream {
print("\(p)")
}
}
private var task: Task<(), Swift.Error>?
let id = UUID()
}
var instance: FailedDeinit? = FailedDeinit()
instance = nil
Run Code Online (Sandbox Code Playgroud)
在 Playground 中运行此代码会产生以下结果:
init() F007863C-9187-4591-A4F4-BC6BC990A935
!!! 该deinit方法从未被调用!
奇怪的是,当我将代码更改为:
class SuccessDeinit {
init() {
print(#function, id) …Run Code Online (Sandbox Code Playgroud) 我有一个 .r32Float 像素格式的 MTLTexture,其值在 0 - 1 范围内。
将该纹理转换为 8 位或 16 位 NSBitmapImageRep 的最佳方法是什么?
metal ×3
swift ×3
macos ×2
async-await ×1
asyncstream ×1
c++ ×1
concurrency ×1
gpu ×1
ios ×1
kernel ×1
task ×1
xcode ×1