Vel*_*its 9 multithreading objective-c grand-central-dispatch ios sprite-kit
我正在开发一个Sprite Kit游戏,我需要做一些多线程来维持健康的fps.
在更新时,我调用一个函数来创建许多UIBezierPaths并使用C++静态库合并它们.
如果我有超过10个形状,帧速率会急剧下降,所以我决定尝试GCD并尝试使用单独的线程来解决问题.
我把它放在didMoveToView中:
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
Run Code Online (Sandbox Code Playgroud)
在每个帧上调用的函数中,我称之为:
dispatch_async(queue,^(void){[self heavyCalculationsFunc];});
Run Code Online (Sandbox Code Playgroud)
对于那些了解GCD的人来说,很明显它会在每一帧上创建一个新线程,但对我来说还不清楚.
我的问题是,有没有办法重新使用我想在更新时调用的线程?
感谢您的帮助!
ric*_*ter 19
如果你需要在每一帧上完成工作,并且需要在渲染帧之前完成,多线程可能无法帮助你,除非你愿意付出很多努力.
保持帧速率几乎是时间 - 而不是CPU资源,只是墙上时间.为了保持60fps的帧速率,你有16.67毫秒的时间来完成所有的工作.(实际上,不到那个,因为SpriteKit和OpenGL需要一些时间来渲染你的工作结果.)这是一个同步问题 - 你有工作,你有一定的时间来完成这项工作,因此提高绩效的第一步是减少工作量或提高效率.
另一方面,多线程通常用于异步问题 - 你需要做的工作,但它现在不需要完成,所以你可以继续你现在需要做的其他事情(比如返回)从你的更新方法在16毫秒内保持你的帧率)并检查以后的工作结果(比如,在后面的帧).
但是,这两个定义之间存在一些摆动空间:几乎所有现代iOS设备都有多核CPU,因此如果你正确地使用你的卡,你可以通过并行化工作负载来适应同步问题中的一些异步性.完成这项工作并做得很好,这不是一件容易的事 - 多年来它一直是大型游戏工作室认真研究和投资的主题.
请参阅SpriteKit编程指南中"场景如何处理动画帧"下的图.那是你的16毫秒时钟.浅蓝色区域是Apple的SpriteKit(和OpenGL以及其他系统框架)代码负责的16 ms的片段.其他片是你的.让我们展开该图表以获得更好的外观:
如果你在任何这些切片中做了太多工作,或者使SpriteKit的工作量太大,整个事情就会超过16毫秒,你的帧率会下降.
线程化的机会是在同一时间线内在另一个CPU上完成一些工作.如果SpriteKit对动作,物理和约束的处理不依赖于那项工作,那么你可以与这些东西并行执行:
或者,如果你的工作需要在SpriteKit运行动作和物理之前发生,但是你需要在update
方法中做其他工作,你可以在完成剩下的工作时将一些工作发送到另一个线程update
,然后检查仍在您的update
方法中的结果:
那么如何完成这些事情呢?这是使用调度组的一种方法,并假设动作/物理/约束不依赖于您的后台工作 - 它完全偏离我的头脑,所以它可能不是最好的.:)
// in setup
dispatch_queue_t workQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_t resultCatchingGroup = dispatch_group_create();
id stuffThatGetsMadeInTheBackground;
- (void)update:(NSTimeInterval)currentTime {
dispatch_group_async(group, queue, ^{
// Do the background work
stuffThatGetsMadeInTheBackground = // ...
});
// Do anything else you need to before actions/physics/constraints
}
- (void)didFinishUpdate {
// wait for results from the background work
dispatch_group_wait(resultCatchingGroup, DISPATCH_TIME_FOREVER);
// use those results
[self doSomethingWith:stuffThatGetsMadeInTheBackground];
}
Run Code Online (Sandbox Code Playgroud)
当然,dispatch_group_wait
顾名思义,阻止执行等待你的后台工作完成,所以你仍然有16ms的时间限制.如果前台工作(你的其余部分update
,加上SpriteKit的动作/物理/约束工作以及你为响应这些事情而完成的任何其他工作)在你的后台工作之前完成,你将等待它.如果背景工作加上SpriteKit的渲染工作(以及update
在产生背景工作之前你做的任何事情)花费的时间超过16毫秒,你仍然会丢帧.因此,解决这个问题的方法是充分了解您的工作量以便安排好.
归档时间: |
|
查看次数: |
1196 次 |
最近记录: |