func(g *UpdateCuda) Execute() {
    kernel := g.GetKernel(g.dtype, g.rs, false, "update")
    g.lib.MemsetD32Async(g.outputData, 0, g.outputDataSize)
    kernel.Launch(g.grid, g.block, 0, g.launchArgs, g.staticArgs)
    g.outputTrans.Execute()
}
SKIPPED: Arguments 'repeat' and 'unbind'
package cuda
import (
    "fmt"
    "fragata/arhat/backends"
    "fragata/arhat/base"
    "fragata/arhat/generators/acc"
    kernels "fragata/arhat/kernels/cuda"
    "strings"
)
type ConvFpropKernels interface {
    BindParams(
        i backends.Tensor,
        f backends.Tensor,
        o backends.Tensor,
        x backends.Tensor,
        bias backends.Tensor,
        bsum backends.Tensor,
        alpha float64,
        beta float64,
        relu bool,
        brelu bool,
        slope float64)
    Execute()
}
type ConvBpropKernels interface {
    BindParams(
        i backends.Tensor,
        f backends.Tensor,
        o backends.Tensor,
        x backends.Tensor,
        bias backends.Tensor,
        bsum backends.Tensor,
        alpha float64,
        beta float64,
        relu bool,
        brelu bool,
        slope float64)
    Execute()
}
type ConvUpdateKernels interface {
    BindParams(
        i backends.Tensor,
        e backends.Tensor,
        o backends.Tensor,
        alpha float64,
        beta float64,
        noOp bool)
    Execute()
}
type KernelGroup struct {
    params ConvParams
    lib *CudaGenerator
    dtype base.Dtype
    kernelName string
}
func(g *KernelGroup) Init(
        lib *CudaGenerator,
        dtype base.Dtype,
        params *ConvParams) {
    g.params = *params
    g.lib = lib
    g.dtype = dtype
    g.kernelName = ""
}
func(g *KernelGroup) GetKernel(
        dtype base.Dtype,
        filterSize int,
        bsum bool,
        operation string) *Kernel {
    key := fmt.Sprintf("conv_%s_%d_%t_%s_false_false", dtype, filterSize, bsum, operation)
    kernel := g.lib.LookupKernel(key)
    if kernel != nil {
        return kernel
    }
    kernel = g.getKernelRaw(dtype, filterSize, bsum, operation)
    g.lib.RegisterKernel(key, kernel)
    return kernel
}
func(g *KernelGroup) getKernelRaw(
        dtype base.Dtype,
        filterSize int,
        bsum bool,
        operation string) *Kernel {
    name, code := kernels.GetConvKernel(dtype, filterSize, bsum, operation, false, false)
    return NewKernel(g.lib, name, code)
}
type FpropCuda struct {
    KernelGroup
    rs int
    grid []int
    block []int
    launchArgs []acc.KernelArgument
    staticArgs []int
    shared int
    outputTrans *CompoundOps
}
func NewFpropCuda(
        lib *CudaGenerator, 
        dtype base.Dtype, 
        params *ConvParams) *FpropCuda {
    g := new(FpropCuda)
    g.Init(lib, dtype, params)
    return g
}
func(g *FpropCuda) Init(
        lib *CudaGenerator, 
        dtype base.Dtype, 
        params *ConvParams) {
    g.KernelGroup.Init(lib, dtype, params)
    g.kernelName = "FpropCuda"
    a := params
    base.AssertMsg(a.N % 32 == 0, "N dim must be multiple of 32")
    var vecSize int
    if dtype.ItemSize() == 4 {
        vecSize = 4
    } else {
        vecSize = 8
    }
    base.AssertMsg(a.K % vecSize == 0, "K dim must be multiple of %d", vecSize)
    magicPq := magic64(a.P*a.Q)
    magicQ := magic64(a.Q)
    magicS := magic32(a.R*a.S+32, a.S)
    hwn := a.H * a.W * a.N
    rst := a.R * a.S * a.T
    krst := a.K * rst
    pq := a.P * a.Q
    pqn := pq * a.N
    g.rs = a.R * a.S
    g.grid = []int{pq * ceilDiv(a.N, 32), ceilDiv(a.K, 32), 1}
    g.block = []int{8, 8, 1}
    g.staticArgs = 
        Flatten(
            a.C, 
            a.D, 
            a.H, 
            a.W, 
            a.N, 
            a.T, 
            a.R, 
            a.S, 
            a.K, 
            a.M, 
            a.P, 
            a.Q,
            a.StrW, 
            a.StrH, 
            a.PadW, 
            a.PadH,
            a.DilW, 
            a.DilH,
            hwn/4, 
            krst/4, 
            pqn/4,
            pq, 
            0, 
            0,
            magicPq, 
            magicQ, 
            magicS)
    g.shared = rst * 4 * 2
    g.outputTrans = NewCompoundOps(lib, dtype, a.K, pqn)
    lib.SetScratchSize(g.outputTrans.size)
}
func(g *FpropCuda) BindParams(
        i backends.Tensor,
        f backends.Tensor,
        o backends.Tensor,
        x backends.Tensor,
        bias backends.Tensor,
        bsum backends.Tensor,
        alpha float64,
        beta float64,
        relu bool,
        brelu bool,
        slope float64) {
    base.Assert(i.Dtype() == g.dtype && f.Dtype() == g.dtype && o.Dtype() == g.dtype)
    g.lib.ScratchBufferInit()
    betaOrSlope := beta
    if betaOrSlope == 0.0 {
        betaOrSlope = slope
    }
    outputData := g.outputTrans.BindParams(o, x, bias, bsum, alpha, betaOrSlope, relu, brelu)
    g.launchArgs = []acc.KernelArgument{1.0, 0.0, i, f, outputData, 0}
}
func(g *FpropCuda) Execute() {
    kernel := g.GetKernel(g.dtype, g.rs, false, "fprop")
    kernel.Launch(g.grid, g.block, g.shared, g.launchArgs, g.staticArgs)
    g.outputTrans.Execute()
}
type BpropCuda struct {
    KernelGroup
    rs int
    grid []int
    block []int
    launchArgs []acc.KernelArgument
    staticArgs []int
    shared int
    filterTrans *FilterDimShuffle
    outputTrans *CompoundOps
}
func NewBpropCuda(
        lib *CudaGenerator, 
        dtype base.Dtype, 
        params *ConvParams) *BpropCuda {
    g := new(BpropCuda)
    g.Init(lib, dtype, params)
    return g
}
func(g *BpropCuda) Init(
        lib *CudaGenerator, 
        dtype base.Dtype, 
        params *ConvParams) {
    g.KernelGroup.Init(lib, dtype, params)
    g.kernelName = "BpropCuda"
    a := params
    base.AssertMsg(a.N % 32 == 0, "N dim must be multiple of 32")
    magicHw := magic64(a.H*a.W)
    magicW := magic64(a.W)
    magicS := magic32(a.R*a.S+32, a.S)
    hw := a.H * a.W
    hwn := hw * a.N
    rst := a.R * a.S * a.T
    crst := a.C * rst
    pq := a.P * a.Q
    pqn := pq * a.N
    g.rs = a.R * a.S
    g.grid = []int{hw * ceilDiv(a.N, 32), ceilDiv(a.C, 32), 1}
    g.block = []int{8, 8, 1}
    g.staticArgs = 
        Flatten(
            a.K, 
            a.M, 
            a.P, 
            a.Q, 
            a.N, 
            a.T, 
            a.R, 
            a.S, 
            a.C, 
            a.D, 
            a.H, 
            a.W,
            a.StrW, 
            a.StrH, 
            a.PadW, 
            a.PadH,
            a.DilW, 
            a.DilH,
            pqn/4, 
            crst/4, 
            hwn/4,
            hw, 
            0, 
            0,
            magicHw, 
            magicW, 
            magicS)
    g.shared = a.R * a.S * a.T * 4 * 2
    g.filterTrans = NewFilterDimShuffle(lib, dtype, a.C, a.T, a.R, a.S, a.K)
    g.outputTrans = NewCompoundOps(lib, dtype, a.C, hwn)
    lib.SetScratchSize(g.filterTrans.size, g.outputTrans.size)
}
func(g *BpropCuda) BindParams(
        i backends.Tensor,
        f backends.Tensor,
        o backends.Tensor,
        x backends.Tensor,
        bias backends.Tensor,
        bsum backends.Tensor,
        alpha float64,
        beta float64,
        relu bool,
        brelu bool,
        slope float64) {
    base.Assert(i.Dtype() == g.dtype && f.Dtype() == g.dtype && o.Dtype() == g.dtype)
    base.AssertMsg(g.params.C % 4 == 0, "C dim must be a multiple of 4 for CUDA bprop kernel")
    g.lib.ScratchBufferInit()
    filterData := g.filterTrans.BindParams(f)
    betaOrSlope := beta
    if betaOrSlope == 0.0 {
        betaOrSlope = slope
    }
    outputData := g.outputTrans.BindParams(o, x, bias, bsum, alpha, betaOrSlope, relu, brelu)
    g.launchArgs = []acc.KernelArgument{1.0, 0.0, i, filterData, outputData, 0}
}
func(g *BpropCuda) Execute() {
    kernel := g.GetKernel(g.dtype, g.rs, false, "bprop")
    g.filterTrans.Execute()
    kernel.Launch(g.grid, g.block, g.shared, g.launchArgs, g.staticArgs)
    g.outputTrans.Execute()
}
type UpdateCuda struct {
    KernelGroup
    rs int
    determ int
    grid []int
    block []int
    launchArgs []acc.KernelArgument
    staticArgs []int
    outputTrans *UpdateConvReduce
    outputData acc.DeviceAllocation
    outputDataSize int
}
func NewUpdateCuda(
        lib *CudaGenerator, 
        dtype base.Dtype, 
        params *ConvParams) *UpdateCuda {
    g := new(UpdateCuda)
    g.Init(lib, dtype, params)
    return g
}
func(g *UpdateCuda) Init(
        lib *CudaGenerator, 
        dtype base.Dtype, 
        params *ConvParams) {
    g.KernelGroup.Init(lib, dtype, params)
    g.kernelName = "UpdateData"
    a := params
    base.AssertMsg(a.N % 32 == 0, "N dim must be multiple of 32")
    hwn := a.H * a.W * a.N
    rs := a.R * a.S
    rst := rs * a.T
    krst := a.K * rst
    crstk := krst * a.C
    pq := a.P * a.Q
    pqn := pq * a.N
    magicS := magic32(a.R*a.S+32, a.S)
    g.rs = a.R * a.S
    var gridP, gridQ int
    if lib.Deterministic() {
        gridP = 1
        gridQ = 1
        g.determ = crstk
    } else {
        gridP = a.P
        gridQ = a.Q
        g.determ = 0
    }
    pqBlocks := gridP * gridQ
    magicPq := magic64(pqBlocks)
    magicQ := magic64(gridQ)
    g.grid = []int{pqBlocks * ceilDiv(a.K, 32), ceilDiv(a.C*rs, 32), 1}
    g.block = []int{8, 32, 1}
    g.staticArgs = 
        Flatten(
            a.C, 
            a.D, 
            a.H, 
            a.W, 
            a.N, 
            a.T, 
            a.R, 
            a.S, 
            a.K, 
            a.M, 
            a.P, 
            a.Q,
            a.StrW, 
            a.StrH, 
            a.PadW, 
            a.PadH,
            a.DilW, 
            a.DilH,
            hwn/4, 
            krst/4, 
            pqn/4,
            pqBlocks, 
            gridP, 
            gridQ,
            magicPq, 
            magicQ, 
            magicS)
    g.outputTrans = NewUpdateConvReduce(lib, 1, crstk)
    lib.SetScratchSize(g.outputTrans.size) 
}
func(g *UpdateCuda) BindParams(
        i backends.Tensor,
        e backends.Tensor,
        o backends.Tensor,
        alpha float64,
        beta float64,
        noOp bool) {
    base.Assert(i.Dtype() == g.dtype && e.Dtype() == g.dtype && o.Dtype() == g.dtype)
    g.lib.ScratchBufferInit()
    g.outputData = g.outputTrans.BindParams(o, alpha, beta, noOp)
    g.outputDataSize = o.Size()
    g.launchArgs = []acc.KernelArgument{1.0, 0.0, i, e, g.outputData, 0}
}