微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

整数双线性插值优化

如何解决整数双线性插值优化

我的代码受到双线性插值的极大限制,所以我编写了一个不使用浮点数学的版本 (ScaleBlerpI)。这已经 1.5 快了 1.85 倍,但我想知道如何让它更快。

感谢任何提示

func ScaleBlerpI(src,dst *ValueFieldI) {
    mx := uint64((src.Width - 1) * math.MaxUint32 / dst.Width)
    my := uint64((src.Height - 1) * math.MaxUint32 / dst.Height)

    for y := uint64(0); y < uint64(dst.Height); y++ {
        for x := uint64(0); x < uint64(dst.Width); x++ {
            gx := (x * mx) >> 32            // eq. / math.MaxUint32
            tx := (x * mx) & math.MaxUint32 // eq. % (math.MaxUint32 + 1) or % 2^32
            gy := (y * my) >> 32
            ty := (y * my) & math.MaxUint32

            srcX,srcY := int(gx),int(gy)
            rgba00 := src.GetComponent(srcX,srcY)
            rgba10 := src.GetComponent(srcX+1,srcY)
            rgba01 := src.GetComponent(srcX,srcY+1)
            rgba11 := src.GetComponent(srcX+1,srcY+1)
            result := []uint32{
                blerpI(rgba00[0],rgba10[0],rgba01[0],rgba11[0],tx,ty),blerpI(rgba00[1],rgba10[1],rgba01[1],rgba11[1],blerpI(rgba00[2],rgba10[2],rgba01[2],rgba11[2],}
            dst.SetComponent(int(x),int(y),result)
        }
    }
}

func lerpI(s,e uint32,f uint64) uint32 {
    // basically s * (1 - f) + b * f
    return uint32(
        (uint64(s)*(math.MaxUint32-f) + uint64(e)*f) /
            math.MaxUint32)
}
func blerpI(c00,c10,c01,c11 uint32,ty uint64) uint32 {
    return lerpI(
        lerpI(c00,tx),lerpI(c01,c11,ty,)
}
type ValueFieldI struct {
    Width,Height int
    ComponentSize int
    Values        []uint32
}

func (vf *ValueFieldI) GetComponent(x,y int) []uint32 {
    componentIdx := x + y*vf.Width
    return vf.Values[componentIdx*vf.ComponentSize : componentIdx*vf.ComponentSize+vf.ComponentSize]
}

func (vf *ValueFieldI) SetComponent(x,y int,c []uint32) {
    copy(vf.GetComponent(x,y),c)
}

分析显示我在 blerpIsrc.GetComponentdst.SetComponent 上浪费的时间最多

编辑 1

已替换

    // basically s * (1 - f) + e * f
    return uint32(
        (uint64(s)*(math.MaxUint32-f) + uint64(e)*f) /
            math.MaxUint32)

    // basically s + f*(e-s)
    return s + uint32((f*(uint64(e)-uint64(s)))>>32)

整数版本现在快 1.85 倍。

编辑 2

基准:

func BenchmarkBlerpIRand(b *testing.B) {
    src := &ValueFieldI{
        Width:         37,Height:        37,ComponentSize: 3,Values:        make([]uint32,37*37*3),}

    for i := range src.Values {
        src.Values[i] = rand.Uint32()
    }

    dst := &ValueFieldI{
        Width:         37 * 8,Height:        37 * 8,37*8*37*8*3),}

    b.ResetTimer()
    for i := 0; i < b.N; i++ {
        ScaleBlerpI(src,dst)
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。