def init(self, params, autotune=False):

        N, C, K, H, W, P, Q, pad_h, pad_w = self.params
        itemsize = self.dtype.itemsize
        R, S = 3, 3

        if N == 1:
            shlN = 0
        elif 16 < N:
            shlN = len(bin(N-1))-2
        else:
            shlN = 4

        GC32 = _ceil_div(C, 32)
        GK32 = _ceil_div(K, 32)
        GC16 = _ceil_div(GC32*32, 16)
        GK16 = _ceil_div(GK32*32, 16)
        GY   = _ceil_div(P, 4)
        GX   = _ceil_div(Q, 4)

        # maximize points of GX in superblock for large GX (most contiguous access)
        if shlN > 1 or GX >= 32:
            shlY, shlX, maskY, shrY, maskX, shrX, maskN = {
                0 : (2, 6, 0x0, 0, 0xf, 0, 0x0), # 1x16 xxxx
                1 : (2, 5, 0x0, 0, 0xe, 1, 0x1), # 1x8  xxxn
                2 : (2, 4, 0x0, 0, 0xc, 2, 0x3), # 1x4  xxnn
                3 : (2, 3, 0x0, 0, 0x8, 3, 0x7), # 1x2  xnnn
                4 : (2, 2, 0x0, 0, 0x0, 0, 0xf), # 1x1  nnnn
            }.get(shlN)
        # As GX gets smaller, add points of y
        elif shlN > 0 or GX >= 16:
            shlY, shlX, maskY, shrY, maskX, shrX, maskN = {
                0 : (3, 5, 0x8, 3, 0x7, 0, 0x0), # 2x8  yxxx
                1 : (3, 4, 0x8, 3, 0x6, 1, 0x1), # 2x4  yxxn
            }.get(shlN)
        # for smallest dimensions, make the superblock square
        else:
            shlY, shlX, maskY, shrY, maskX, shrX, maskN = {
                0 : (4, 4, 0xc, 2, 0x3, 0, 0x0), # 4x4  yyxx
            }.get(shlN)

        GYS     = _ceil_div(P, 1 << shlY)
        GXS     = _ceil_div(Q, 1 << shlX)
        GN16    = _ceil_div(N, 1 << shlN)
        GYS2    = GYS // 2
        GXS2    = GXS  * 2
        groupC  = 2
        groupK  = 2
        groupN  = 1 if GN16 & 1 else 2
        shift_c = groupC - 1
        shift_k = groupK - 1
        shift_n = groupN - 1

        X2cn       = GXS2*groupC*groupN
        Xkn        = GXS*groupK*groupN
        magic_X2cn = _magic64(X2cn)
        magic_Xkn  = _magic64(Xkn)

        self.image_size = GC32*GY*GX*N*1152*itemsize
        self.image_args = [
            ( GYS*GXS*groupC*groupN, GN16//groupN, GC16//groupC ), (256,1,1), None, None, None,
            C, H, W, N, pad_h, pad_w,
            GY, GX, GXS, GYS2, X2cn, magic_X2cn[0], magic_X2cn[1], shift_c, shift_n,
            shlY, shlX, maskY, shrY, maskX, shrX, shlN, maskN,
            H*W*N, W*N, GY*GX*N*1152, GX*N*1152, N*1152]

        self.delta_size = GK32*GY*GX*N*1152*itemsize
        self.delta_args = [
            ( GYS*GXS*groupK*groupN, GN16//groupN, GK16//groupK ), (256,1,1), None, None, None,
            K, P, Q, N, GY, GX,
            Xkn, magic_Xkn[0], magic_Xkn[1], shift_k, shift_n,
            shlY, shlX, maskY, shrY, maskX, shrX, shlN, maskN,
            P*Q*N, Q*N, GY*GX*N*1152, GX*N*1152, N*1152]

        Gc = _closest_divisor(GC32, 4)
        Gk = _closest_divisor(GK32, 4)
        GC = GC32 // Gc
        GK = GK32 // Gk
        kc = Gk*Gc
        YXN  = GY*GX*N
        YXN2 = self.YXN2 = _ceil_div(YXN, 2)

        self.maxYXN2 = max(1, YXN2 // N)

        if autotune:
            strideYXN = autotune
        else:
            autotune_db  = shelve.open(self.autotune_db_file)
            autotune_key = " ".join(self.autotune_key)

            if autotune_key in autotune_db:
                strideYXN = autotune_db[autotune_key]
                #print strideYXN, autotune_key
                self.initialized = True
            else:
                strideYXN = self.maxYXN2
                self.initialized = False

            autotune_db.close()

        self.blocksCK = GC32 * GK32
        magic_sYXN    = _magic64(strideYXN)
        magic_kc      = _magic64(kc)
        magic_c       = _magic32(kc, Gc)

        # If output grid is 1, don't use atomics.  Kernel is deterministic by default
        if strideYXN == 1:
            determ = "D"
            self.determ_size  = 0
            self.determ_shape = False
            self.zero         = False
        elif self.lib.deterministic:
            determ = "D"
            self.determ_size  = strideYXN * C*R*S*K
            self.determ_shape = (strideYXN, C*R*S*K)
            self.zero         = False
        else:
            determ = ""
            self.determ_size  = 0
            self.determ_shape = False
            self.zero         = True

        kernel_name = "%s_winograd%s_3x3_4x4_32x32" % (self.clss, determ)

        #print strideYXN*Gk*Gc, strideYXN, Gk, Gc, strideYXN*Gk*Gc*GC*GK, YXN2//strideYXN

        self.kernel = [
            kernel_name, (strideYXN*Gk*Gc, GC, GK), (640, 1, 1), None,
            None, None, None, None]

        self.kernel.extend( _flatten([
            K, C, Gk, Gc, kc, magic_kc, magic_c, YXN2, strideYXN, magic_sYXN,
            strideYXN*2*1152*itemsize, YXN, YXN*1152, R*S*K, C*R*S*K,
            K*4, S*K*4, (R*S*K*15 - S*K*2)*4 ]))
dataset/ETHPy150Open NervanaSystems/neon/neon/backends/winograd_conv.py/UpdateWinograd_3x3_4x4.init/swapped operands of `<`