我创建了简单的直通计算内核
kernel void filter(texture2d<float, access::read> inTexture [[texture(0)]],
texture2d<float, access::write> outTexture [[texture(1)]],
uint2 gridPos [[ thread_position_in_grid ]]) {
float4 color = inTexture.read(gridPos);
outTexture.write(color, gridPos);
}
测量执行时间
[self.timer start];
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
CGFloat ms = [self.timer elapse];
计时器类的工作方式如下:
- (void)start {
self.startMach = mach_absolute_time();
}
- (CGFloat)elapse {
uint64_t end = mach_absolute_time();
uint64_t elapsed = end - self.startMach;
uint64_t nanosecs = elapsed * self.info.numer / self.info.denom;
uint64_t millisecs = nanosecs / 1000000;
return millisecs;
}
调度呼叫:
static const NSUInteger kGroupSize = 16;
- (MTLSize)threadGroupSize {
return MTLSizeMake(kGroupSize, kGroupSize, 1);
}
- (MTLSize)threadGroupsCount:(MTLSize)threadGroupSize {
return MTLSizeMake(self.provider.texture.width / kGroupSize,
self.provider.texture.height / kGroupSize, 1);
}
[commandEncoder dispatchThreadgroups:threadgroups
threadsPerThreadgroup:threadgroupSize];
在 512x512 RGBA 图像上给我 13 毫秒,如果我执行更多传递,它会变线性。
这是对的吗?对于实时应用程序来说,开销似乎太大了。
众所周知,计算内核在 A7 处理器上的开销相当高。但是,需要考虑的一件事是,这基本上是您可以运行的最不讨人喜欢的测试:一次性线程组调度可能需要 ~2ms 才能调度,但后续调度的调度速度可以快一个数量级。此外,延迟隐藏在这里的可能性很小。实际上,更复杂的内核可能不会花费更长的时间来执行,并且如果可以将其与可能正在执行的任何渲染交错,您可能会发现性能是可以接受的。