code: def _add_functionality():
      def device_get_attributes(dev):
          result = {}
  
          for att_name in dir(device_attribute):
              if not att_name[0].isupper():
                  continue
  
              att_id = getattr(device_attribute, att_name)
  
              try:
                  att_value = dev.get_attribute(att_id)
              except LogicError as e:
                  from warnings import warn
  
                  warn(
                      "CUDA driver raised '%s' when querying '%s' on '%s'"
                      % (e, att_name, dev)
                  )
              else:
                  result[att_id] = att_value
  
          return result
  
      def device___getattr__(dev, name):
          return dev.get_attribute(
              getattr(device_attribute, name.upper())
          )
  
      def _build_arg_buf(args):
          handlers = []
  
          arg_data = []
          format = ""
          for i, arg in enumerate(args):
              if isinstance(arg, np.number):
                  arg_data.append(arg)
                  format += arg.dtype.char
              elif isinstance(
                  arg, (DeviceAllocation, PooledDeviceAllocation)
              ):
                  arg_data.append(int(arg))
                  format += "P"
              elif isinstance(arg, ArgumentHandler):
                  handlers.append(arg)
                  arg_data.append(int(arg.get_device_alloc()))
                  format += "P"
              elif isinstance(arg, np.ndarray):
                  if isinstance(arg.base, ManagedAllocationOrStub):
                      arg_data.append(int(arg.base))
                      format += "P"
                  else:
                      arg_data.append(arg)
                      format += "%ds" % arg.nbytes
              elif isinstance(arg, np.void):
                  arg_data.append(_my_bytes(_memoryview(arg)))
                  format += "%ds" % arg.itemsize
              else:
                  cai = getattr(arg, "__cuda_array_interface__", None)
                  if cai:
                      arg_data.append(cai["data"][0])
                      format += "P"
                      continue
  
                  try:
                      gpudata = np.uintp(arg.gpudata)
                  except AttributeError:
                      raise TypeError(
                          "invalid type on parameter #%d (0-based)" % i
                      )
                  else:
                      # for gpuarrays
                      arg_data.append(int(gpudata))
                      format += "P"
  
          from pycuda._pvt_struct import pack
  
          return handlers, pack(format, *arg_data)
  
      # {{{ pre-CUDA 4 call interface (stateful)
  
      def function_param_set_pre_v4(func, *args):
          handlers = []
  
          handlers, buf = _build_arg_buf(args)
  
          func._param_setv(0, buf)
          func._param_set_size(len(buf))
  
          return handlers
  
      def function_call_pre_v4(func, *args, **kwargs):
          grid = kwargs.pop("grid", (1, 1))
          stream = kwargs.pop("stream", None)
          block = kwargs.pop("block", None)
          shared = kwargs.pop("shared", None)
          texrefs = kwargs.pop("texrefs", [])
          time_kernel = kwargs.pop("time_kernel", False)
  
          if kwargs:
              raise ValueError(
                  "extra keyword arguments: %s"
                  % (",".join(kwargs.keys()))
              )
  
          if block is None:
              raise ValueError("must specify block size")
  
          func._set_block_shape(*block)
          handlers = func._param_set(*args)
          if shared is not None:
              func._set_shared_size(shared)
  
          for handler in handlers:
              handler.pre_call(stream)
  
          for texref in texrefs:
              func.param_set_texref(texref)
  
          post_handlers = [
              handler
              for handler in handlers
              if hasattr(handler, "post_call")
          ]
  
          if stream is None:
              if time_kernel:
                  Context.synchronize()
  
                  from time import time
  
                  start_time = time()
              func._launch_grid(*grid)
              if post_handlers or time_kernel:
                  Context.synchronize()
  
                  if time_kernel:
                      run_time = time() - start_time
  
                  for handler in post_handlers:
                      handler.post_call(stream)
  
                  if time_kernel:
                      return run_time
          else:
              assert (
                  not time_kernel
              ), "Can't time the kernel on an asynchronous invocation"
              func._launch_grid_async(grid[0], grid[1], stream)
  
              if post_handlers:
                  for handler in post_handlers:
                      handler.post_call(stream)
  
      def function_prepare_pre_v4(
          func, arg_types, block=None, shared=None, texrefs=[]
      ):
          from warnings import warn
  
          if block is not None:
              warn(
                  "setting the block size in Function.prepare is deprecated",
                  DeprecationWarning,
                  stacklevel=2,
              )
              func._set_block_shape(*block)
  
          if shared is not None:
              warn(
                  "setting the shared memory size in Function.prepare is deprecated",
                  DeprecationWarning,
                  stacklevel=2,
              )
              func._set_shared_size(shared)
  
          func.texrefs = texrefs
  
          func.arg_format = ""
  
          for i, arg_type in enumerate(arg_types):
              if (
                  isinstance(arg_type, type)
                  and np is not None
                  and np.number in arg_type.__mro__
              ):
                  func.arg_format += np.dtype(arg_type).char
              elif isinstance(arg_type, str):
                  func.arg_format += arg_type
              else:
                  func.arg_format += np.dtype(np.uintp).char
  
          from pycuda._pvt_struct import calcsize
  
          func._param_set_size(calcsize(func.arg_format))
  
          return func
  
      def function_prepared_call_pre_v4(
          func, grid, block, *args, **kwargs
      ):
          if isinstance(block, tuple):
              func._set_block_shape(*block)
          else:
              from warnings import warn
  
              warn(
                  "Not passing the block size to prepared_call is deprecated as of "
                  "version 2011.1.",
                  DeprecationWarning,
                  stacklevel=2,
              )
              args = (block,) + args
  
          shared_size = kwargs.pop("shared_size", None)
          if shared_size is not None:
              func._set_shared_size(shared_size)
  
          if kwargs:
              raise TypeError(
                  "unknown keyword arguments: "
                  + ", ".join(kwargs.keys())
              )
  
          from pycuda._pvt_struct import pack
  
          func._param_setv(0, pack(func.arg_format, *args))
  
          for texref in func.texrefs:
              func.param_set_texref(texref)
  
          func._launch_grid(*grid)
  
      def function_prepared_timed_call_pre_v4(
          func, grid, block, *args, **kwargs
      ):
          if isinstance(block, tuple):
              func._set_block_shape(*block)
          else:
              from warnings import warn
  
              warn(
                  "Not passing the block size to prepared_timed_call is "
                  "deprecated as of version 2011.1.",
                  DeprecationWarning,
                  stacklevel=2,
              )
              args = (block,) + args
  
          shared_size = kwargs.pop("shared_size", None)
          if shared_size is not None:
              func._set_shared_size(shared_size)
  
          if kwargs:
              raise TypeError(
                  "unknown keyword arguments: "
                  + ", ".join(kwargs.keys())
              )
  
          from pycuda._pvt_struct import pack
  
          func._param_setv(0, pack(func.arg_format, *args))
  
          for texref in func.texrefs:
              func.param_set_texref(texref)
  
          start = Event()
          end = Event()
  
          start.record()
          func._launch_grid(*grid)
          end.record()
  
          def get_call_time():
              end.synchronize()
              return end.time_since(start) * 1e-3
  
          return get_call_time
  
      def function_prepared_async_call_pre_v4(
          func, grid, block, stream, *args, **kwargs
      ):
          if isinstance(block, tuple):
              func._set_block_shape(*block)
          else:
              from warnings import warn
  
              warn(
                  "Not passing the block size to prepared_async_call is "
                  "deprecated as of version 2011.1.",
                  DeprecationWarning,
                  stacklevel=2,
              )
              args = (stream,) + args
              stream = block
  
          shared_size = kwargs.pop("shared_size", None)
          if shared_size is not None:
              func._set_shared_size(shared_size)
  
          if kwargs:
              raise TypeError(
                  "unknown keyword arguments: "
                  + ", ".join(kwargs.keys())
              )
  
          from pycuda._pvt_struct import pack
  
          func._param_setv(0, pack(func.arg_format, *args))
  
          for texref in func.texrefs:
              func.param_set_texref(texref)
  
          if stream is None:
              func._launch_grid(*grid)
          else:
              grid_x, grid_y = grid
              func._launch_grid_async(grid_x, grid_y, stream)
  
      # }}}
  
      # {{{ CUDA 4+ call interface (stateless)
  
      def function_call(func, *args, **kwargs):
          grid = kwargs.pop("grid", (1, 1))
          stream = kwargs.pop("stream", None)
          block = kwargs.pop("block", None)
          shared = kwargs.pop("shared", 0)
          texrefs = kwargs.pop("texrefs", [])
          time_kernel = kwargs.pop("time_kernel", False)
  
          if kwargs:
              raise ValueError(
                  "extra keyword arguments: %s"
                  % (",".join(kwargs.keys()))
              )
  
          if block is None:
              raise ValueError("must specify block size")
  
          func._set_block_shape(*block)
          handlers, arg_buf = _build_arg_buf(args)
  
          for handler in handlers:
              handler.pre_call(stream)
  
          for texref in texrefs:
              func.param_set_texref(texref)
  
          post_handlers = [
              handler
              for handler in handlers
              if hasattr(handler, "post_call")
          ]
  
          if stream is None:
              if time_kernel:
                  Context.synchronize()
  
                  from time import time
  
                  start_time = time()
  
              func._launch_kernel(grid, block, arg_buf, shared, None)
  
              if post_handlers or time_kernel:
                  Context.synchronize()
  
                  if time_kernel:
                      run_time = time() - start_time
  
                  for handler in post_handlers:
                      handler.post_call(stream)
  
                  if time_kernel:
                      return run_time
          else:
              assert (
                  not time_kernel
              ), "Can't time the kernel on an asynchronous invocation"
              func._launch_kernel(grid, block, arg_buf, shared, stream)
  
              if post_handlers:
                  for handler in post_handlers:
                      handler.post_call(stream)
  
      def function_prepare(func, arg_types, texrefs=[]):
          func.texrefs = texrefs
  
          func.arg_format = ""
  
          for i, arg_type in enumerate(arg_types):
              if (
                  isinstance(arg_type, type)
                  and np.number in arg_type.__mro__
              ):
                  func.arg_format += np.dtype(arg_type).char
              elif isinstance(arg_type, np.dtype):
                  if arg_type.char == "V":
                      func.arg_format += "%ds" % arg_type.itemsize
                  else:
                      func.arg_format += arg_type.char
              elif isinstance(arg_type, str):
                  func.arg_format += arg_type
              else:
                  func.arg_format += np.dtype(np.uintp).char
  
          return func
  
      def function_prepared_call(func, grid, block, *args, **kwargs):
          if isinstance(block, tuple):
              func._set_block_shape(*block)
          else:
              from warnings import warn
  
              warn(
                  "Not passing the block size to prepared_call is deprecated as of "
                  "version 2011.1.",
                  DeprecationWarning,
                  stacklevel=2,
              )
              args = (block,) + args
  
          shared_size = kwargs.pop("shared_size", 0)
  
          if kwargs:
              raise TypeError(
                  "unknown keyword arguments: "
                  + ", ".join(kwargs.keys())
              )
  
          from pycuda._pvt_struct import pack
  
          arg_buf = pack(func.arg_format, *args)
  
          for texref in func.texrefs:
              func.param_set_texref(texref)
  
          func._launch_kernel(grid, block, arg_buf, shared_size, None)
  
      def function_prepared_timed_call(
          func, grid, block, *args, **kwargs
      ):
          shared_size = kwargs.pop("shared_size", 0)
          if kwargs:
              raise TypeError(
                  "unknown keyword arguments: "
                  + ", ".join(kwargs.keys())
              )
  
          from pycuda._pvt_struct import pack
  
          arg_buf = pack(func.arg_format, *args)
  
          for texref in func.texrefs:
              func.param_set_texref(texref)
  
          start = Event()
          end = Event()
  
          start.record()
          func._launch_kernel(grid, block, arg_buf, shared_size, None)
          end.record()
  
          def get_call_time():
              end.synchronize()
              return end.time_since(start) * 1e-3
  
          return get_call_time
  
      def function_prepared_async_call(
          func, grid, block, stream, *args, **kwargs
      ):
          if isinstance(block, tuple):
              func._set_block_shape(*block)
          else:
              from warnings import warn
  
              warn(
                  "Not passing the block size to prepared_async_call is "
                  "deprecated as of version 2011.1.",
                  DeprecationWarning,
                  stacklevel=2,
              )
              args = (stream,) + args
              stream = block
  
          shared_size = kwargs.pop("shared_size", 0)
  
          if kwargs:
              raise TypeError(
                  "unknown keyword arguments: "
                  + ", ".join(kwargs.keys())
              )
  
          from pycuda._pvt_struct import pack
  
          arg_buf = pack(func.arg_format, *args)
  
          for texref in func.texrefs:
              func.param_set_texref(texref)
  
          func._launch_kernel(grid, block, arg_buf, shared_size, stream)
  
      # }}}
  
      def function___getattr__(self, name):
          if get_version() >= (2, 2):
              return self.get_attribute(
                  getattr(function_attribute, name.upper())
              )
          else:
              if name == "num_regs":
                  return self._hacky_registers
              elif name == "shared_size_bytes":
                  return self._hacky_smem
              elif name == "local_size_bytes":
                  return self._hacky_lmem
              else:
                  raise AttributeError(
                      "no attribute '%s' in Function" % name
                  )
  
      def mark_func_method_deprecated(func):
          def new_func(*args, **kwargs):
              from warnings import warn
  
              warn(
                  "'%s' has been deprecated in version 2011.1. Please use "
                  "the stateless launch interface instead."
                  % func.__name__[1:],
                  DeprecationWarning,
                  stacklevel=2,
              )
              return func(*args, **kwargs)
  
          try:
              from functools import update_wrapper
          except ImportError:
              pass
          else:
              try:
                  update_wrapper(new_func, func)
              except Exception:
                  # User won't see true signature. Oh well.
                  pass
  
          return new_func
  
      Device.get_attributes = device_get_attributes
      Device.__getattr__ = device___getattr__
  
      if get_version() >= (4,):
          Function.__call__ = function_call
          Function.prepare = function_prepare
          Function.prepared_call = function_prepared_call
          Function.prepared_timed_call = function_prepared_timed_call
          Function.prepared_async_call = function_prepared_async_call
      else:
          Function._param_set = function_param_set_pre_v4
          Function.__call__ = function_call_pre_v4
          Function.prepare = function_prepare_pre_v4
          Function.prepared_call = function_prepared_call_pre_v4
          Function.prepared_timed_call = (
              function_prepared_timed_call_pre_v4
          )
          Function.prepared_async_call = (
              function_prepared_async_call_pre_v4
          )
  
          for meth_name in [
              "set_block_shape",
              "set_shared_size",
              "param_set_size",
              "param_set",
              "param_seti",
              "param_setf",
              "param_setv",
              "launch",
              "launch_grid",
              "launch_grid_async",
          ]:
              setattr(
                  Function,
                  meth_name,
                  mark_func_method_deprecated(
                      getattr(Function, "_" + meth_name)
                  ),
              )
  
      Function.__getattr__ = function___getattr__
  
imports: import os
  import numpy
label_desc: Use image node_id 4 for calling a global function with example usage: _add_functionality() and returns: result, dev, handlers,  pack, handlers, func, get_call_time, func, get_call_time, new_func, unknown, unknown, self, func, self, run_time, run_time, self, self