Use Accelerate to improve performance and incorporate encrypted archives
System & Services 高级 20m

用 Accelerate 提升性能并集成加密归档

Use Accelerate to improve performance and incorporate encrypted archives

2021年6月10日

在 Apple 官方观看视频

一句话判断

Accelerate 框架在 iOS 15 中新增了加密归档(Encrypted Archive)支持——用 Apple 独有的加密算法压缩和保护数据,性能比 CommonCrypto 好得多。

这场 Session 讲了什么

Session 分为两部分:前半部分介绍了 Accelerate 框架的性能优化能力,后半部分重点讲解了新增的加密归档 API。

Accelerate 是 Apple 的底层计算框架,提供向量运算、矩阵运算、信号处理和图像处理的硬件加速实现。Session 展示了几个常见的使用场景:用 vDSP 做音频处理、用 vImage 做图像处理、用 BNNS 做简单的神经网络推理。这些操作用 Accelerate 比用纯 Swift 实现快 10-100 倍。

加密归档是 iOS 15 中新增的功能。它提供了端到端加密的压缩归档格式,基于 Apple 的专有算法(结合了 AES 和自定义压缩)。主要用例是安全地在设备和服务器之间传输敏感数据,或在本地安全存储加密备份。

值得深挖的点

加密归档 vs CommonCrypto

CommonCrypto 提供 AES 等标准加密算法,但它只管加密不管压缩和归档。如果你要”加密压缩一堆文件”,需要自己组合压缩(zlib)和加密(AES),还要处理文件元数据的保护。加密归档 API 把这些一步到位——创建归档时同时压缩和加密,读取时同时解密和解压。而且 Apple 的实现利用了硬件加速的 AES 指令,性能比 CommonCrypto 的软件实现快。

vDSP 在音频处理中的实际收益

Session 用一个音频频谱分析的例子展示了 vDSP 的威力。对一段音频做 FFT(快速傅里叶变换),纯 Swift 实现需要几百毫秒,vDSP 只需要不到 1 毫秒。差距来自 vDSP 直接调用 Neon SIMD 指令,一个 CPU 周期处理 4 个浮点数。

代码片段

创建和读取加密归档

import Accelerate

// 创建加密归档
func createEncryptedArchive(data: Data, password: String) throws -> Data {
    let archive = try EncryptedArchive.create(
        data: data,
        password: password,
        compression: .lz4  // 使用 LZ4 压缩算法
    )
    return archive
}

// 读取加密归档
func readEncryptedArchive(archiveData: Data, password: String) throws -> Data {
    let data = try EncryptedArchive.open(
        data: archiveData,
        password: password
    )
    return data
}

使用 vDSP 做音频 FFT

import Accelerate

// 计算音频数据的频谱
func computeSpectrum(audioSamples: [Float]) -> [Float] {
    let length = audioSamples.count
    let log2n = vDSP_Length(log2(Float(length)))
    
    // 创建 FFT setup
    let fftSetup = vDSP_create_fftsetup(log2n, FFTRadix(kFFTRadix2))!
    
    // 将音频数据拆分为实部和虚部
    var realPart = [Float](repeating: 0, count: length / 2)
    var imagPart = [Float](repeating: 0, count: length / 2)
    
    audioSamples.withUnsafeBufferPointer { samples in
        var splitComplex = DSPSplitComplex(realp: &realPart, imagp: &imagPart)
        // 执行 FFT
        vDSP_fft_zrip(fftSetup, &splitComplex, 1, log2n, FFTDirection(FFT_FORWARD))
    }
    
    // 计算幅度
    var magnitudes = [Float](repeating: 0, count: length / 2)
    var splitComplex = DSPSplitComplex(realp: &realPart, imagp: &imagPart)
    vDSP_zvabs(&splitComplex, 1, &magnitudes, 1, vDSP_Length(length / 2))
    
    vDSP_destroy_fftsetup(fftSetup)
    return magnitudes
}

使用 vImage 做图像处理

import Accelerate

// 高效调整图片大小(比 UIKit 的缩放快 5-10 倍)
func resizeImage(source: CGImage, targetSize: CGSize) -> CGImage? {
    let sourceWidth = vImagePixelCount(source.width)
    let sourceHeight = vImagePixelCount(source.height)
    let destWidth = vImagePixelCount(Int(targetSize.width))
    let destHeight = vImagePixelCount(Int(targetSize.height))
    
    var sourceBuffer = vImage_CGImageFormat(
        bitsPerComponent: 8, bitsPerPixel: 32,
        colorSpace: CGColorSpaceCreateDeviceRGB(),
        bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.first.rawValue)
    )!.createBuffer(from: source)!
    
    var destBuffer = vImage_Buffer()
    vImageBuffer_Init(&destBuffer, destHeight, destWidth, 32, vImage_Flags(kvImageNoFlags))
    
    // Lanczos 重采样,质量高于双线性插值
    vImageScale_ARGB8888(&sourceBuffer, &destBuffer, nil, vImage_Flags(kvImageHighQualityResampling))
    
    return destBuffer.createCGImage(format: sourceBuffer.format)
}

最佳实践

性能敏感场景: 任何涉及大量浮点运算的场景(音频处理、图像处理、科学计算)都应该用 Accelerate 而不是纯 Swift。vDSP 用于 1D 信号,vImage 用于 2D 图像,vForce 用于数学函数。这些 API 直接调用 CPU 的 SIMD 指令,无法被编译器自动优化替代。

加密存储: 需要加密归档数据的场景(离线缓存敏感数据、导出加密备份),使用新的加密归档 API 比 CommonCrypto + zlib 的组合更简单更安全。但注意加密归档格式是 Apple 专有的,无法在非 Apple 平台上读取。

还有什么值得关注

  • Accelerate 的 BNNS(Basic Neural Network Subroutines)支持了更多层的类型,可以用来做轻量的推理任务。
  • vImage 新增了对多平面图像格式的支持(如 YUV 420),方便视频处理。
  • 加密归档支持增量写入,适合大文件的加密传输。
WWDC 2021