code: def run(self, max_iterations=None, tol=1e-7, debug_callback=None):
      check_interval = 20
  
      if max_iterations is None:
          max_iterations = max(
              3 * check_interval + 1, 10 * self.operator.shape[0]
          )
      real_resid_interval = min(self.operator.shape[0], 50)
  
      iterations = 0
      delta_0 = None
      while iterations < max_iterations:
          compute_real_residual = iterations % real_resid_interval == 0
  
          self.one_iteration(
              compute_real_residual=compute_real_residual
          )
  
          if debug_callback is not None:
              if compute_real_residual:
                  what = "it+residual"
              else:
                  what = "it"
  
              debug_callback(
                  what,
                  iterations,
                  self.x,
                  self.residual,
                  self.d,
                  self.delta,
              )
  
          # do often enough to allow AsyncInnerProduct
          # to progress through (polled) event chain
          rdq = self.real_delta_queue
          if iterations % check_interval == 0:
              if delta_0 is None:
                  delta_0 = rdq[0].get_host_result()
                  if delta_0 is not None:
                      rdq.pop(0)
  
              if delta_0 is not None:
                  i = 0
                  while i < len(rdq):
                      delta = rdq[i].get_host_result()
                      if delta is not None:
                          if abs(delta) < tol * tol * abs(delta_0):
                              if debug_callback is not None:
                                  debug_callback(
                                      "end",
                                      iterations,
                                      self.x,
                                      self.residual,
                                      self.d,
                                      self.delta,
                                  )
                              return self.x
                          rdq.pop(i)
                      else:
                          i += 1
  
          iterations += 1
  
      raise ConvergenceError("cg failed to converge")
  
file_path: pycuda/pycuda/sparse/cg.py
imports: from __future__ import division
  from __future__ import absolute_import
  from pycuda.sparse.inner import AsyncInnerProduct
  from pytools import memoize_method
  import pycuda.driver
  import pycuda.gpuarray
  import numpy
label_desc: Use image node_id 8 for calling the CGStateContainer obj's underlying member method code with example usage: obj.run(max_iterations, tol, debug_callback) and returns: self