def autotune(self, I, E, O):

        autotune_key = " ".join(self.autotune_key)
        #print "autotune: ", self.autotune_key

        # Only need to do warmup once
        if not self.lib.warmup:
            self.lib.warmup = True
            # warmup  with a conservative set of params
            self.init(self.params, autotune=self.maxYXN2)
            self.bind_params(I, E, O, 1.0)
            self.execute(repeat=self.warmup, unbind=False)

        start, stop = self.lib.get_events()
        block_slots = _get_sm_count()
        small_set   = self.YXN2 < 512
        YXN2        = float(self.YXN2)
        results     = []
        sys.stdout.write("Autotune " + str(self))
        progress = 0
        for threshold in (True, False):
            for strideYXN in range(1, self.maxYXN2 + 1):
                if progress % 32 == 0:
                    sys.stdout.write('.')
                    sys.stdout.flush()
                progress += 1
                # minimal occupancy filter
                blocks  = self.blocksCK * strideYXN
                # gemm loop count filter
                depth   = YXN2 / strideYXN

                filters = blocks >= block_slots and blocks <= 24*block_slots and depth >= 32.0

                # In case we filter out all settings, run though the loops again
                # this time looking only at settings that didn't pass.
                if small_set or (threshold and filters) or (not threshold and not filters):

                    self.init(self.params, autotune=strideYXN)
                    self.bind_params(I, E, O, 1.0)
                    start.record(stream=self.lib.stream)
                    self.execute(repeat=2, unbind=False)
                    stop.record(stream=self.lib.stream)
                    stop.synchronize()
                    msecs = stop.time_since(start) / 2.0
                    results.append((msecs, strideYXN))

                    #print strideYXN, msecs, blocks, round(depth,1)

                # else:
                #     print strideYXN, blocks, round(depth,1)

            # if we got any results, no need to disable the filter
            if len(results) > 0:
                break
        sys.stdout.write('\n')

        results.sort()
        strideYXN = results[0][1]
        # for res in results[0:10]:
        #     print res

        autotune_db = shelve.open(self.autotune_db_file)
        autotune_db[autotune_key] = strideYXN

        # add a copy if this layer has small strides
        # deterministic vs non-determ should make no speed difference here
        if strideYXN <= 8:
            self.autotune_key[2] = str(1 - int(self.autotune_key[2]))
            autotune_key = " ".join(self.autotune_key)
            autotune_db[autotune_key] = strideYXN

        autotune_db.close()

        self.init(self.params, autotune=strideYXN)
dataset/ETHPy150Open NervanaSystems/neon/neon/backends/winograd_conv.py/UpdateWinograd_3x3_4x4.autotune/original