Fab*_*ato 5 performance multithreading opengl-es objective-c ios
我正在开发一个模拟器作为一个侧面/有趣的项目,但我遇到了一些性能问题,并且没有弄清楚它们来自哪里.
该应用程序主要由用于显示的GLKView和用于cpu仿真的具有无限循环的单独线程组成.这是一个示例,其中包含所有实际仿真代码,但仍然显示问题:
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
GLKView *glView = [[GLKView alloc] initWithFrame:self.view.bounds];
glView.delegate = self;
glView.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:glView.context];
[self.view addSubview:glView];
glView.enableSetNeedsDisplay = NO;
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:glView selector:@selector(display)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
dispatch_get_main_queue(), ^{
dispatch_async(dispatch_queue_create("yeah", DISPATCH_QUEUE_SERIAL), ^{
CFTimeInterval lastTime = 0;
CFTimeInterval time = 0;
int instructions = 0;
while(1) {
// here be cpu emulation
if (lastTime == 0) {
lastTime = CACurrentMediaTime();
} else {
CFTimeInterval newTime = CACurrentMediaTime();
time += newTime - lastTime;
lastTime = newTime;
}
if (++instructions == 1000) {
printf("%f\n", 1/(time * 1000));
time = 0;
instructions = 0;
}
}
});
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
// Here be graphics
}
@end
Run Code Online (Sandbox Code Playgroud)
像这样,无限循环基本上只是计算它的迭代并以MHz为单位打印出它的频率.
所以,问题是,当应用程序启动时,循环运行在大约9-15 MHz(在iPhone6上),如果我查看Xcode的Debug Navigator中的GPU报告,我可以看到CPU帧时间是0.2ms然后,在运行几秒钟后,循环降至1-5 MHz,CPU帧时间增加到0.6 ms
如果我禁用GLKView更新,那么循环永远不会变慢
我也尝试使用不同的线程API(gdc,NSThread,pthread),但这似乎没有任何影响
我的问题是,我在某处做错了吗?这只是一个GLKView没有完全初始化几秒钟的情况,所以使用比正常情况更少的CPU,我得到一个速度提升?我可以通过其他任何方式构建代码以获得循环中的最佳性能吗?
更新 我做了一些测试,并注意到在使用CAEAGLLayer而不是GLKView时也存在问题,并且它不会在模拟器上发生,仅在设备上发生.我还尝试使用NSOpenGLView的OS X应用程序,它也不会发生......
更新2 我尝试在一段时间后启动线程而不是立即启动线程,如果延迟大于通常需要的时间,则线程开始已经放慢了...不确定要做什么. ..
Metal Update 我尝试使用Metal而不是OpenGL,使用简单的Xcode库存模板,它也随之发生......
操作系统可以降低 CPU 频率以消耗更少的能量/节省电池。如果您的线程没有使用太多 CPU 功率,那么操作系统会认为现在是降低频率的好时机。另一方面,在台式计算机上,有许多其他线程/进程正在运行(并且阈值可能非常不同),这可能就是它似乎在模拟器/桌面应用程序中工作的原因。
有多种可能的原因可以解释为什么您的线程被检测为不消耗太多 CPU 时间。一种是您调用 printf,并且内部可能存在某种锁使您的线程等待(也可能是 CACurrentMediaTime)。另一个可能与 GLKView 更新相关,尽管我不确定如何。