maymaymaymaymay
maymaymaymaymay

Reputation: 31

App uses CoreML with GPU in the foreground fails to switch to CPU when app goes to background

I am working with Swift to implement CoreML in an iOS app. When in foreground, I want CoreML to use GPU for performance enhancement, however when switch to background, CoreML should use CPU because by iOS, GPU is not able to run in background.

However, during background, GPU is throwing permission error saying that there is no permission to use GPU in the background. But in the code i have already registered CoreML to use CPU only whenever the app is in the background, but it seems like the CoreML class is not reading the parameter.

Error message obtained when CoreML is running in background, despite setting usesCpuOnly to true

2019-07-23 12:04:21.747498+0800 Demo[351:9947] Execution of the command buffer was aborted due to an error during execution. Insufficient Permission (to submit GPU work from background) (IOAF code 6)
Error: command buffer exited with error status.
    The Metal Performance Shaders operations encoded on it may not have completed.
    Error: 
    (null)
    Insufficient Permission (to submit GPU work from background) (IOAF code 6)
    <AGXA9FamilyCommandBuffer: 0x106b70720>
    label = <none> 
    device = <AGXA9Device: 0x10bdc4000>
        name = Apple A9 GPU 
    commandQueue = <AGXA9FamilyCommandQueue: 0x106a7f670>
        label = <none> 
        device = <AGXA9Device: 0x10bdc4000>
            name = Apple A9 GPU 
    retainedReferences = 1
2019-07-23 12:04:21.748800+0800 Demo[351:9982] [espresso] [Espresso::handle_ex_plan] exception=Espresso exception: "Generic error": Insufficient Permission (to submit GPU work from background) (IOAF code 6); code=7 status=-1
2019-07-23 12:04:21.749744+0800 Demo[351:9982] [StarMobile] [ERROR] CoreMLClassifier:112 processClassifications(for:error:) error: Unable to classify image. : Optional(Error Domain=com.apple.vis Code=9 "Could not run network (-1: ESPRESSO_STATUS_ERROR_GENERIC)" UserInfo={NSLocalizedDescription=Could not run network (-1: ESPRESSO_STATUS_ERROR_GENERIC)})
2019-07-23 12:04:21.750350+0800 Demo[351:9982] [StarMobile] [ERROR] CoreMLClassifier:105 updateClassifications(for:as:) Failed to perform classification.
Could not run network (-1: ESPRESSO_STATUS_ERROR_GENERIC)

Please help!

// AppDelegate.swift
func applicationWillResignActive(_ application: UIApplication) {
    Constants.APP_IS_IN_FOREGROUND = false
}
func applicationDidBecomeActive(_ application: UIApplication) {
    Constants.APP_IS_IN_FOREGROUND = true
}

// Main.swift
class Main() {
    func run_coreml(imageData: Data) {
        do {
            self.usesCpuOnly = Constants.APP_IS_IN_FOREGROUND
            let configuration = MLModelConfiguration()
            if self.usesCpuOnly {
                 configuration.computeUnits = .cpuOnly
            } else {
                 configuration.computeUnits = .all
            }
            let model = try VNCoreMLModel(for: 
            CoreMLImageClassifier(configuration: configuration).model)

            let request = VNCoreMLRequest(model: model, 
            completionHandler: 
            { [weak self] request, error in
                 self?.process(for: request, error: error)
            })
            request.usesCPUOnly = self.usesCpuOnly

            let handler = VNImageRequestHandler(data: imageData)
            try handler.perform([request])
         } catch {}
    }

   // omit implementation
   func process() {}
}

Upvotes: 1

Views: 1691

Answers (1)

Matthijs Hollemans
Matthijs Hollemans

Reputation: 7892

When the app goes into the background, you will need to create a new VNCoreMLModel instance with the configuration set to .cpuOnly, and make a new VNCoreMLRequest. Core ML doesn't automagically switch from GPU to CPU.

Upvotes: 1

Related Questions