Open GL +无限循环使神秘性能下降

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库存模板,它也随之发生......

Jer*_*rem 2

操作系统可以降低 CPU 频率以消耗更少的能量/节省电池。如果您的线程没有使用太多 CPU 功率,那么操作系统会认为现在是降低频率的好时机。另一方面,在台式计算机上,有许多其他线程/进程正在运行(并且阈值可能非常不同),这可能就是它似乎在模拟器/桌面应用程序中工作的原因。

有多种可能的原因可以解释为什么您的线程被检测为不消耗太多 CPU 时间。一种是您调用 printf,并且内部可能存在某种锁使您的线程等待(也可能是 CACurrentMediaTime)。另一个可能与 GLKView 更新相关,尽管我不确定如何。