Section 10/161 menit

10. Model Optimization: Compute Units

10. Model Optimization: Compute Units

Memilih compute unit yang tepat memiliki dampak signifikan pada latensi, throughput, dan konsumsi baterai.

Benchmark Compute Units

swift
import CoreML

class ModelBenchmark {
    func benchmark(modelURL: URL, sampleInput: MLFeatureProvider) async throws {
        let computeUnits: [(MLComputeUnits, String)] = [
            (.cpuOnly, "CPU Only"),
            (.cpuAndGPU, "CPU + GPU"),
            (.cpuAndNeuralEngine, "CPU + ANE"),
            (.all, "All (Auto)")
        ]
        
        for (unit, name) in computeUnits {
            let config = MLModelConfiguration()
            config.computeUnits = unit
            
            let model = try MLModel(contentsOf: modelURL, configuration: config)
            
            // Warm-up run (penting untuk benchmark yang akurat)
            _ = try model.prediction(from: sampleInput)
            
            // Benchmark 10 runs
            let start = Date()
            for _ in 0..<10 {
                _ = try model.prediction(from: sampleInput)
            }
            let avgMs = Date().timeIntervalSince(start) * 100  // ms per run
            
            print("\(name): \(String(format: "%.1f", avgMs))ms avg")
        }
    }
}

Model Quantization

Quantization mengurangi ukuran model dan mempercepat inferensi dengan trade-off akurasi minimal:

swift
# Script Python: quantize model sebelum distribute
import coremltools as ct

model = ct.models.MLModel("MyModel.mlpackage")

# Float16 quantization — ukuran 50% lebih kecil, minimal accuracy loss
config = ct.optimize.coreml.OptimizationConfig(
    global_config=ct.optimize.coreml.OpLinearQuantizerConfig(
        mode="linear_symmetric",
        dtype="float16"
    )
)
compressed_model = ct.optimize.coreml.linear_quantize_weights(model, config=config)
compressed_model.save("MyModel_Float16.mlpackage")

# Int8 quantization — ukuran 75% lebih kecil, sedikit accuracy loss
config_int8 = ct.optimize.coreml.OptimizationConfig(
    global_config=ct.optimize.coreml.OpLinearQuantizerConfig(
        mode="linear_symmetric",
        dtype="int8"
    )
)
compressed_int8 = ct.optimize.coreml.linear_quantize_weights(model, config_int8)
compressed_int8.save("MyModel_Int8.mlpackage")

Compute Plan API (iOS 17+): Inspect Before Execute

swift
// Inspect bagaimana Core ML akan mengeksekusi model SEBELUM load
func inspectComputePlan(modelURL: URL) async throws {
    let config = MLModelConfiguration()
    config.computeUnits = .all
    
    // Dapatkan plan tanpa load model sepenuhnya
    let plan = try await MLComputePlan.load(contentsOf: modelURL, configuration: config)
    
    // Iterasi struktur model
    for (index, layer) in plan.modelStructure.program?.functions["main"]?.block.operations.enumerated() ?? [].enumerated() {
        let deviceUsage = plan.computeDeviceUsage(for: layer)
        
        let device: String
        switch deviceUsage?.preferred {
        case .some(let cpu as MLCPUComputeDevice): device = "CPU"
        case .some(let gpu as MLGPUComputeDevice): device = "GPU"
        case .some(let ane as MLNeuralEngineComputeDevice): device = "ANE"
        default: device = "Unknown"
        }
        
        print("Layer \(index): \(device)")
    }
}