Local variables =============== .. note:: - :samp:`NUMBA_OPT=0` "no optimization" level - all local variables of the kernel function are available. - :samp:`NUMBA_OPT=1` or higher - some variables may be optimized out. Consider Numba-dppy kernel code :file:`sum_local_vars.py` .. literalinclude:: ../../../numba_dppy/examples/debug/sum_local_vars.py :lines: 15- :linenos: :lineno-match: ``info locals`` --------------- Run the debugger: .. literalinclude:: ../../../numba_dppy/examples/debug/commands/docs/local_variables_0 :language: shell-session :lines: 1-6 Run the ``info locals`` command. The sample output on "no optimization" level ``NUMBA_OPT=0`` is as follows: .. literalinclude:: ../../../numba_dppy/examples/debug/commands/docs/local_variables_0 :language: shell-session :lines: 8-48 :emphasize-lines: 1-16, 24-39 Since the debugger does not hit a line with the target variable ``l1``, the value equals 0. The true value of the variable ``l1`` is shown after stepping to line 22. .. literalinclude:: ../../../numba_dppy/examples/debug/commands/docs/local_variables_0 :language: shell-session :lines: 49-66 :emphasize-lines: 1-16 When the debugger hits the last line of the kernel, ``info locals`` command returns all the local variables with their values. .. note:: The debugger can show the variable values, but these values may be equal to 0 after the variable is explicitly deleted or the function scope is ended. For more info see :ref:`local-variables-lifetime`. When you use "O1 optimization" level ``NUMBA_OPT=1`` and run the ``info locals`` command, the output is as follows: .. literalinclude:: ../../../numba_dppy/examples/debug/commands/docs/local_variables_1 :language: shell-session :lines: 8-23 :emphasize-lines: 1-14 .. note:: The debugger does not show the local variables ``a``, ``b`` and ``c``, they are optimized out on "O1 optimization" level. ``print `` ------------------ To print the value of a variable, run the ``print `` command. .. literalinclude:: ../../../numba_dppy/examples/debug/commands/docs/local_variables_0 :language: shell-session :lines: 67-72 :emphasize-lines: 1-6 .. note:: Kernel variables are shown in intermidiate representation view (with "$" sign). The actual values of the arrays are currently not available. ``ptype `` ------------------ To print the type of a variable, run the ``ptype `` or ``whatis `` commands: .. literalinclude:: ../../../numba_dppy/examples/debug/commands/docs/local_variables_0 :language: shell-session :lines: 73-81 :emphasize-lines: 1-6 See also: - `Local variables in GDB* `_ .. _local-variables-lifetime: Lifetime of local variables --------------------------- Numba uses live variable analysis. Lifetime of Python variables are different from lifetime of variables in compiled code. .. note:: For more information, refer to `Numba variable policy `_. It affects debugging experience in following way. Consider Numba-dppy kernel code from :file:`sum_local_vars.py`: .. literalinclude:: ../../../numba_dppy/examples/debug/sum_local_vars.py :lines: 20-25 :linenos: :lineno-match: Run this code with environment variable :samp:`NUMBA_DUMP_ANNOTATION=1` and it will show where numba inserts `del` for variables. .. code-block:: :linenos: :emphasize-lines: 28 -----------------------------------ANNOTATION----------------------------------- # File: numba_dppy/examples/debug/sum_local_vars.py # --- LINE 20 --- @dppy.kernel(debug=True) # --- LINE 21 --- def data_parallel_sum(a, b, c): # --- LINE 22 --- # label 0 # a = arg(0, name=a) :: array(float32, 1d, C) # b = arg(1, name=b) :: array(float32, 1d, C) # c = arg(2, name=c) :: array(float32, 1d, C) # $2load_global.0 = global(dppy: ) :: Module() # $4load_method.1 = getattr(value=$2load_global.0, attr=get_global_id) :: Function() # del $2load_global.0 # $const6.2 = const(int, 0) :: Literal[int](0) # i = call $4load_method.1($const6.2, func=$4load_method.1, args=[Var($const6.2, sum_local_vars.py:22)], kws=(), vararg=None, target=None) :: (uint32,) -> int64 # del $const6.2 # del $4load_method.1 i = dppy.get_global_id(0) # --- LINE 23 --- # $16binary_subscr.6 = getitem(value=a, index=i, fn=) :: float32 # del a # $const18.7 = const(float, 2.5) :: float64 # l1 = $16binary_subscr.6 + $const18.7 :: float64 # del $const18.7 # del $16binary_subscr.6 l1 = a[i] + 2.5 # --- LINE 24 --- # $28binary_subscr.11 = getitem(value=b, index=i, fn=) :: float32 # del b # $const30.12 = const(float, 0.3) :: float64 # l2 = $28binary_subscr.11 * $const30.12 :: float64 # del $const30.12 # del $28binary_subscr.11 l2 = b[i] * 0.3 # --- LINE 25 --- # $40binary_add.16 = l1 + l2 :: float64 # del l2 # del l1 # c[i] = $40binary_add.16 :: (array(float32, 1d, C), int64, float64) -> none # del i # del c # del $40binary_add.16 # $const48.19 = const(NoneType, None) :: none # $50return_value.20 = cast(value=$const48.19) :: none # del $const48.19 # return $50return_value.20 c[i] = l1 + l2 I.e. in `LINE 23` variable `a` used the last time and numba inserts `del a` as shown in annotated code in line 28. It means you will see value 0 for the variable `a` when you set breakpoint at `LINE 24`. As a workaround you can expand lifetime of the variable by using it (i.e. passing to dummy function `revive()`) at the end of the function. So numba will not insert `del a` until the end of the function. .. literalinclude:: ../../../numba_dppy/examples/debug/sum_local_vars_revive.py :lines: 20-31 :linenos: :lineno-match: .. code-block:: :linenos: :emphasize-lines: 59 -----------------------------------ANNOTATION----------------------------------- # File: numba_dppy/examples/debug/sum_local_vars_revive.py # --- LINE 24 --- @dppy.kernel(debug=True) # --- LINE 25 --- def data_parallel_sum(a, b, c): # --- LINE 26 --- # label 0 # a = arg(0, name=a) :: array(float32, 1d, C) # b = arg(1, name=b) :: array(float32, 1d, C) # c = arg(2, name=c) :: array(float32, 1d, C) # $2load_global.0 = global(dppy: ) :: Module() # $4load_method.1 = getattr(value=$2load_global.0, attr=get_global_id) :: Function() # del $2load_global.0 # $const6.2 = const(int, 0) :: Literal[int](0) # i = call $4load_method.1($const6.2, func=$4load_method.1, args=[Var($const6.2, sum_local_vars_revive.py:26)], kws=(), vararg=None, target=None) :: (uint32,) -> int64 # del $const6.2 # del $4load_method.1 i = dppy.get_global_id(0) # --- LINE 27 --- # $16binary_subscr.6 = getitem(value=a, index=i, fn=) :: float32 # $const18.7 = const(float, 2.5) :: float64 # l1 = $16binary_subscr.6 + $const18.7 :: float64 # del $const18.7 # del $16binary_subscr.6 l1 = a[i] + 2.5 # --- LINE 28 --- # $28binary_subscr.11 = getitem(value=b, index=i, fn=) :: float32 # del b # $const30.12 = const(float, 0.3) :: float64 # l2 = $28binary_subscr.11 * $const30.12 :: float64 # del $const30.12 # del $28binary_subscr.11 l2 = b[i] * 0.3 # --- LINE 29 --- # $40binary_add.16 = l1 + l2 :: float64 # del l2 # del l1 # c[i] = $40binary_add.16 :: (array(float32, 1d, C), int64, float64) -> none # del i # del c # del $40binary_add.16 c[i] = l1 + l2 # --- LINE 30 --- # $48load_global.19 = global(revive: ) :: Function() # $52call_function.21 = call $48load_global.19(a, func=$48load_global.19, args=[Var(a, sum_local_vars_revive.py:26)], kws=(), vararg=None, target=None) :: (array(float32, 1d, C),) -> array(float32, 1d, C) # del a # del $52call_function.21 # del $48load_global.19 # $const56.22 = const(NoneType, None) :: none # $58return_value.23 = cast(value=$const56.22) :: none # del $const56.22 # return $58return_value.23 revive(a) # pass variable to dummy function