首页 > 其他分享 >关于CoreML需要外部生成randn这档子事

关于CoreML需要外部生成randn这档子事

时间:2024-10-02 19:12:04浏览次数:8  
标签:count arr randn CoreML shape let 档子 gen Float32

coremltools在转换后会固定randn结果,实现真·randn需要外部生成,再使用MLMultiArray作为输入参数传入。

太长不看

使用BNNS

import Accelerate
import CoreML

@available(iOS 16.0, *)
extension MLMultiArray {
    
    static func randnFP32(shape: consuming [NSNumber], mean: Float = 0, std: Float = 1) throws -> MLMultiArray {
        let arr = try MLMultiArray(shape: shape, dataType: .float32)
        let cnt = arr.count
        
        arr.withUnsafeMutableBufferPointer(ofType: Float.self) { ptr, strides in
            guard var des = BNNSNDArrayDescriptor(data: ptr, shape: .vector(cnt)),
                  let gen = BNNSCreateRandomGenerator(BNNSRandomGeneratorMethodAES_CTR, nil)
            else { fatalError() }
            BNNSRandomFillNormalFloat(gen, &des, mean, std)
            BNNSDestroyRandomGenerator(gen)
        }
        return arr
    }
}

胡乱折腾

已FP32为例,iOS上(个人尝试)大概3种randn实现方法。

  1. BoxMuller (手动)

    torch有实现,直接抄一遍。

    func boxMuller(count: Int) -> [Float32] {
        let mean: Float32 = 0, std: Float32 = 1
        var arr = (0..<(count/16 + 1) * 16).map { _ in Float32.random(in: 0..<1) }
        for i in stride(from: 0, to: arr.count, by: 16) {
            for j in i..<(i+8) {
                let u1 = 1 - arr[j]
                let u2 = arr[j + 8]
                let radius = sqrt(-2 * log(u1))
                let theta = 2 * Float32.pi * u2
                
                arr[j] = radius * cos(theta) * std + mean
                arr[j+8] = radius * sin(theta) * std + mean
            }
        }
        return arr
    }
    

    循环生成,缺乏加速,tensor增长后性能退化最明显。

  2. MPS

    BoxMuller 由 MPSGraph 提供。

    import MetalPerformanceShadersGraph
    
    @available(iOS 15.4, *)
    func mps(count: Int, seed: Int = .random(in: 0..<Int.max)) -> [Float32] {
        guard let op = MPSGraphRandomOpDescriptor(distribution: .normal, dataType: .float32) else { fatalError() }
        op.samplingMethod = .boxMuller
        let graph = MPSGraph()
        
        let y = graph.randomTensor(withShape: [count as NSNumber], descriptor: consume op, seed: seed, name: nil)
        
        guard let yData = graph.run(
            feeds: [:],
            targetTensors: [y],
            targetOperations: nil
        )[consume y] else { fatalError() }
        
        var arr = [Float32](repeating: 0, count: count)
        yData.mpsndarray().readBytes(&arr, strideBytes: nil)
        return arr
    }
    

    虽然用上GPU是件美事,然鹅在输入多为MLMultiArray的情况下,独立使用缺乏优势。除非后续网络全部接入计算图,配合编译优化才有搞头。此处只能抛砖引玉。

    众所周知,比起算力瓶颈,IO更易拖后腿。

  3. BNSS

    爱,来自Accelerate。

    import Accelerate
    
    @available(iOS 16.0, *)
    func bnns(count: Int) -> [Float32] {
        let mean: Float32 = 0, std: Float32 = 1
        let arr = [Float32](unsafeUninitializedCapacity: count) { buffer, initializedCount in
            guard var des = BNNSNDArrayDescriptor(data: buffer, shape: .vector(count)),
                  let gen = BNNSCreateRandomGenerator(BNNSRandomGeneratorMethodAES_CTR, nil)
            else { fatalError() }
            
            BNNSRandomFillNormalFloat(gen, &des, mean, std)
            BNNSDestroyRandomGenerator(gen)
            initializedCount = count
        }
        return arr
    }
    

    虽然不是真BoxMuller,无法满足强迫症的严谨追求,但在生成2k随机数的 Jarque–Bera test下各方法都只剩随机波动。

    MLTensor表现上似是BNNS封装,但不知为啥性能退化;懒癌发作,放弃探究。

    在绝对的性能面前,一切纠结都是纸老虎。

性能测试

参考价值有限,各方法一次生成[100, 1000, 10_000, 100_000]个随机数

方法 耗时(ms)
BNNS 2
MPS 74
BoxMuller (手动) 148

标签:count,arr,randn,CoreML,shape,let,档子,gen,Float32
From: https://www.cnblogs.com/Simon-X/p/18444993

相关文章

  • 如何使用我的 CoreML 模型在 Vision 中获取 MLMultiArray 输出
    我正在尝试在swift中将我的CoreMl模型与Vision框架结合使用。我的模型输出一个MLMultiArray。当我通过Vision运行它时,我确实得到了一个输出,但是输出的类型是VNObservation,我无法使用它,也无法将其转换为MLMultiArray。有谁知道如何获取MLMultiArray作为输出,或将VNOb......
  • Python【19】 torch.randn( ) 返回标准正态分布张量
    参考:https://pytorch.org/docs/stable/generated/torch.randn.html......
  • 编译 CoreML 模型
    本篇文章译自英文文档CompileCoreMLModels作者是JoshuaZ.Zhang,KazutakaMorita,ZhaoWu更多TVM中文文档可访问→ApacheTVM是一个端到端的深度学习编译框架,适用于CPU、GPU和各种机器学习加速芯片。|ApacheTVM中文站本文介绍如何用Relay部署CoreML模型。首先......
  • iOS MachineLearning 系列(20)—— 训练生成CoreML模型
    iOSMachineLearning系列(20)——训练生成CoreML模型本系列前面的文章详细的介绍了在iOS中与AI能力相关的API的使用,也介绍了如何使用训练好的CoreML模型来实现更强大的AI能力。然而,无论是成熟的API提供的能力,还是各种各样的三方模型,有时候都并不能满足某一领域内的定制化需求。当我......
  • iOS MachineLearning 系列(20)—— 训练生成CoreML模型
    iOSMachineLearning系列(20)——训练生成CoreML模型本系列前面的文章详细的介绍了在iOS中与AI能力相关的API的使用,也介绍了如何使用训练好的CoreML模型来实现更强大的AI能力。然而,无论是成熟的API提供的能力,还是各种各样的三方模型,有时候都并不能满足某一领域内的定制化需求。当我......
  • iOS MachineLearning 系列(17)—— 几个常用的对象识别 CoreML 模型
    iOSMachineLearning系列(17)——几个常用的对象识别CoreML模型上一篇文章中,我们介绍了几个官方的图片分类的模型,图片分类模型的应用场景在于将图片中最主要的事物进行识别,在已有的词库中找到最可能得事物。而对象识别则要更高级一些。再之前的文章,我们介绍过可以使用官方提供的......
  • 关于我被叫做天才、鬼才这档子事
    顾名思义是被叫,这件事这是百度贴吧截图,反正真有人这么叫的。还不少,我也不想说具体,这是很平常的事。他们为什么这么叫,主要是我的一些能力太吓人。我解一个题几分钟,普通需......
  • 调用torch.randn(1, n_mels, 3000).to(device)时报错RuntimeError: CUDA error: devic
    调试Whisper时,不管执行什么命令都会报错RuntimeError:CUDAerror:device-sideasserttriggered问题这个错误通常意味着CUDA运行时检测到了某些问题,例如尝试访问不存在......
  • randn和rand和randi
    rand生成均匀分布的伪随机数,分布在(0,1)之间,例如rand(m)生成m行m列的均匀分布的伪随机数,rand(m,n)生成m行n列的均匀分布的伪随机数,rand(m,n,’double’)生成指定精度的伪随机......
  • matlab生成随机数的rand、randi和randn三种形式
    matlab中关于随机数的产生有3种库函数,下面我们来看看它们的形式:1、rand(…)它是生成0~1之间(开环,不包含0和1两个数)均匀分布的伪随机数,也就是无穷次试验其中每个数产生的概......