Skip to content

Commit eec46fc

Browse files
authored
Merge pull request #161 from jpmorgan98/main
Adding Caching and a Debug Runtime Option
2 parents 9ef1d04 + 2b529bd commit eec46fc

File tree

10 files changed

+162
-40
lines changed

10 files changed

+162
-40
lines changed

.github/workflows/python-publish.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
# separate terms of service, privacy policy, and support
77
# documentation.
88

9+
# assumming this is being done in a repo with trusted publishing permissions in pypi
10+
911
name: Upload Python Package
1012

1113
on:
@@ -17,10 +19,10 @@ permissions:
1719

1820
jobs:
1921
deploy:
20-
2122
runs-on: ubuntu-latest
22-
23-
steps:
23+
permissions:
24+
id-token: write
25+
steps:
2426
- uses: actions/checkout@v3
2527
- name: Set up Python 3.11
2628
uses: actions/setup-python@v3
@@ -38,8 +40,9 @@ jobs:
3840
bash .github/workflows/patch.sh
3941
- name: Build package
4042
run: python -m build
41-
- name: Publish package
42-
uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29
43+
- name: Publish package distributions to PyPI
44+
uses: pypa/gh-action-pypi-publish@release/v1
45+
4346
#with:
4447
# user: __token__
4548
# password: ${{ secrets.PYPI_API_TOKEN }}

docs/paper.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ We have implemented novel algorithms using this scheme and, in some verification
107107
It uses the Numba compiler for Python to compile compute kernels to a desired hardware target, including support for graphics processing units (GPUs) [@lam_numba_2015].
108108
`MC/DC` uses `mpi4py` for distributed-memory parallelism [@mpi4py_2021] and has run at the scale of tens of thousands of processors [@variansyah_mc23_mcdc].
109109
These acceleration and abstraction techniques allow `MC/DC` developers to remain in a pure Python development environment without needing to support compiled or domain-specific languages.
110-
This has allowed `MC/DC` to grow from its instantiation less than two years ago into a codebase that supports full performant neutron transport and investigation of novel transport algorithms, with development mostly from relative novices.
110+
This has allowed `MC/DC` to grow from its initialization less than two years ago into a codebase that supports full performant neutron transport and investigation of novel transport algorithms, with development mostly from relative novices.
111111

112112
Many of the traditionally developed neutron-transport codes are export-controlled (i.e., are not open source and difficult to access) and notoriously difficult to install, use, and develop in.
113113
Because `MC/DC` is an open-source and easily installable Python package (with a `pip`-installable distribution), it is ideal for use in an academic environment for both research and education.

docs/source/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"sphinx.ext.autosummary",
4343
"sphinx_toolbox.github",
4444
"sphinx_toolbox.sidebar_links",
45+
"sphinx.ext.autosectionlabel",
4546
]
4647
autosummary_generate = True
4748

docs/source/contribution.rst

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,64 @@ It's pretty easy to do this locally, just run,
3030
3131
in the top level MC/DC directory and all necessary changes will be automatically made for you.
3232

33+
---------
34+
Debugging
35+
---------
36+
37+
MCDC includes options to debug the Numba JIT code.
38+
It does this by toggling Numba options using the numba.config submodule.
39+
This will result in less performant code and longer compile times but will allow for better error messages from Numba and other packages.
40+
`See Numba documentation of a list of all possible debug and compiler options. <https://numba.readthedocs.io/en/stable/reference/envvars.html#debugging>`_
41+
The most useful set of debug options for MC/DC can be enabled with
42+
43+
.. code-block:: python3
44+
45+
python input.py --mode=numba_debug
46+
47+
Which will toggle the following debug and compiler options in Numba:
48+
49+
* ``DISABLE_JIT=False`` turns on the jitter
50+
* ``NUMBA_OPT=0`` Forces the compilers to form un-optimized code (other options for this are ``1``, ``2``, and ``3`` with ``3`` being the most optimized). This option might need to be changed if errors only result from more optimization.
51+
* ``DEBUG=False`` turns on all debugging options. This is still disabled in ``mcdc numba_debug`` as it will print ALOT of info on your terminal screen
52+
* ``NUMBA_FULL_TRACEBACKS=1`` allows errors from sub-packages to be printed (i.e. Numpy)
53+
* ``NUMBA_BOUNDSCHECK=1`` numba will check vectors for bounds errors. If this is disabled it bound errors will result in a ``seg_fault``. This in consort with the previous option allows for the exact location of a bound error to be printed from Numpy subroutines
54+
* ``NUMBA_DEBUG_NRT=1`` enables the `Numba run time (NRT) statistics counter <https://numba.readthedocs.io/en/stable/developer/numba-runtime.html>`_ This helps with debugging memory leaks.
55+
* ``NUMBA_DEBUG_TYPEINFER= 1`` print out debugging information about type inferences that numba might need to make if a function is ill-defined
56+
* ``NUMBA_ENABLE_PROFILING=1`` enables profiler use
57+
* ``NUMBA_DUMP_CFG=1`` prints out a control flow diagram
58+
59+
If extra debug options or alteration to these options are required they can be toggled and passed under the ``mode==numba_debug`` option tree near the top of ``mcdc/main.py``.
60+
61+
-------
62+
Caching
63+
-------
64+
65+
MC/DC is a just-in-time (JIT) compiled code.
66+
This is sometimes disadvantageous, especially for users who might run many versions of the same simulation with slightly different parameters.
67+
As the JIT compilation scheme will only compile functions that are actually used in a given simulation, it is not a grantee that any one function will be compiled.
68+
69+
Developers should be very cautious about using caching features.
70+
Numba has a few documented errors around caching.
71+
The most critical of which is that functions in other files that are called by cached functions will not force a recompile, even if there are changes in those sub-functions.
72+
In this case caching should be disabled.
73+
74+
In MC/DC the outer most loop functions (in ``mcdc/loop.py``) are called to be cached.
75+
This is done with a option on the jit flag above the individual function declarations like
76+
77+
.. code-block:: python3
78+
79+
nb.njit(cache=True)
80+
def loop_fixed_source(mcdc):
81+
# Loop over
82+
...
83+
84+
To disable caching toggle these jit flags from ``True`` to ``False``.
85+
Alteratively a developer could delete the ``__pycache__`` directory or other cache directory which is system dependent (`see more about clearing the numba cache <https://numba.readthedocs.io/en/stable/developer/caching.html>`_)
86+
87+
88+
At some point MC/DC will enable `Numba's Ahead of Time compilation abilities <https://numba.readthedocs.io/en/stable/user/pycc.html>`_. But the core development team is holding off until scheduled `upgrades to AOT functionality in Numba are implemented <https://numba.readthedocs.io/en/stable/reference/deprecation.html#deprecation-numba-pycc>`_.
89+
However if absolutely required by users numba does allow for some `cache sharing <https://numba.readthedocs.io/en/stable/developer/caching.html>`_.
90+
3391
-------
3492
Testing
3593
-------

docs/source/user.rst

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,23 @@ Numba Mode
203203
204204
python input.py --mode=numba
205205
206+
When running in Numba mode a significant amount of time is taken compiling Python functions to performant binaries.
207+
Only functions used in a specific simulation will be compiled.
208+
These binaries will be cached meaning that in subsequent runs of the same simulation the compilation step can be avoided.
209+
The cache can be used as an effective ahead of time compilation scheme where binaries can be compiled once and shared between machines.
210+
For more information on caching see :ref:`Caching` and `Numba Caching <https://numba.readthedocs.io/en/stable/developer/caching.html>`_.
211+
212+
MC/DC also has the ability to run Numba in a debugging mode.
213+
This will result in less performant code and longer compile times but will allow for better error messages from Numba and other packages.
214+
215+
.. code-block:: python3
216+
217+
python input.py --mode=numba_debug
218+
219+
220+
For more information on the exact behavior of this option see :ref:`Debugging`
221+
222+
206223
Using MPI
207224
^^^^^^^^^
208225

@@ -216,6 +233,7 @@ Below, ``--mode`` can equal python or numba.
216233
srun python input.py --mode=<python/numba>
217234
218235
236+
219237
Postprocessing Results
220238
----------------------
221239

mcdc/loop.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,13 @@
2323
# Fixed-source loop
2424
# =========================================================================
2525

26+
# about caching:
27+
# it is enabled as a default at the jit call level
28+
# to effectivly disable cache, delete the cache folder (often located in /MCDC/mcdc/__pycache__)
29+
# see more about cacheing here https://numba.readthedocs.io/en/stable/developer/caching.html
2630

27-
@njit
31+
32+
@njit(cache=True)
2833
def loop_fixed_source(mcdc):
2934
# Loop over batches
3035
for idx_batch in range(mcdc["setting"]["N_batch"]):
@@ -89,7 +94,7 @@ def loop_fixed_source(mcdc):
8994
# =========================================================================
9095

9196

92-
@njit
97+
@njit(cache=True)
9398
def loop_eigenvalue(mcdc):
9499
# Loop over power iteration cycles
95100
for idx_cycle in range(mcdc["setting"]["N_cycle"]):
@@ -128,7 +133,7 @@ def loop_eigenvalue(mcdc):
128133
# =============================================================================
129134

130135

131-
@njit
136+
@njit(cache=True)
132137
def loop_source(seed, mcdc):
133138
# Progress bar indicator
134139
N_prog = 0
@@ -210,7 +215,7 @@ def loop_source(seed, mcdc):
210215
# =========================================================================
211216

212217

213-
@njit
218+
@njit(cache=True)
214219
def loop_particle(P, mcdc):
215220
# Particle tracker
216221
if mcdc["setting"]["track_particle"]:
@@ -303,7 +308,7 @@ def loop_particle(P, mcdc):
303308
# =============================================================================
304309

305310

306-
@njit
311+
@njit(cache=True)
307312
def loop_iqmc(mcdc):
308313
# function calls from specified solvers
309314
iqmc = mcdc["technique"]["iqmc"]
@@ -320,7 +325,7 @@ def loop_iqmc(mcdc):
320325
gmres(mcdc)
321326

322327

323-
@njit
328+
@njit(cache=True)
324329
def source_iteration(mcdc):
325330
simulation_end = False
326331
iqmc = mcdc["technique"]["iqmc"]
@@ -358,7 +363,7 @@ def source_iteration(mcdc):
358363
total_source_old = iqmc["total_source"].copy()
359364

360365

361-
@njit
366+
@njit(cache=True)
362367
def gmres(mcdc):
363368
"""
364369
GMRES solver.
@@ -513,7 +518,7 @@ def gmres(mcdc):
513518
return
514519

515520

516-
@njit
521+
@njit(cache=True)
517522
def power_iteration(mcdc):
518523
simulation_end = False
519524
iqmc = mcdc["technique"]["iqmc"]
@@ -559,7 +564,7 @@ def power_iteration(mcdc):
559564
print_iqmc_eigenvalue_exit_code(mcdc)
560565

561566

562-
@njit
567+
@njit(cache=True)
563568
def davidson(mcdc):
564569
"""
565570
The generalized Davidson method is a Krylov subspace method for solving
@@ -669,7 +674,7 @@ def davidson(mcdc):
669674
# =============================================================================
670675

671676

672-
@njit
677+
@njit(cache=True)
673678
def loop_source_precursor(seed, mcdc):
674679
# TODO: censussed neutrons seeding is still not reproducible
675680

mcdc/main.py

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,74 @@
1-
import argparse, os
1+
import argparse, os, sys
22
import numba as nb
33

44
# Parse command-line arguments
55
# TODO: Will be inside run() once Python/Numba adapter is integrated
66
parser = argparse.ArgumentParser(description="MC/DC: Monte Carlo Dynamic Code")
77
parser.add_argument(
8-
"--mode", type=str, help="Run mode", choices=["python", "numba"], default="python"
8+
"--mode",
9+
type=str,
10+
help="Run mode",
11+
choices=["python", "numba", "numba_debug"],
12+
default="python",
913
)
1014
parser.add_argument("--N_particle", type=int, help="Number of particles")
1115
parser.add_argument("--output", type=str, help="Output file name")
1216
parser.add_argument("--progress_bar", default=True, action="store_true")
1317
parser.add_argument("--no-progress_bar", dest="progress_bar", action="store_false")
1418
args, unargs = parser.parse_known_args()
1519

20+
from mcdc.print_ import (
21+
print_banner,
22+
print_msg,
23+
print_runtime,
24+
print_header_eigenvalue,
25+
print_warning,
26+
)
27+
1628
# Set mode
1729
# TODO: Will be inside run() once Python/Numba adapter is integrated
1830
mode = args.mode
1931
if mode == "python":
2032
nb.config.DISABLE_JIT = True
2133
elif mode == "numba":
2234
nb.config.DISABLE_JIT = False
35+
nb.config.NUMBA_DEBUG_CACHE = 1
36+
elif mode == "numba_debug":
37+
msg = "\n >> Entering numba debug mode\n >> will result in slower code and longer compile times\n >> to configure debug options see main.py"
38+
print_warning(msg)
39+
40+
nb.config.DISABLE_JIT = False # turns on the jitter
41+
nb.config.DEBUG = False # turns on debugging options
42+
nb.config.NUMBA_FULL_TRACEBACKS = (
43+
1 # enables errors from sub-packages to be printed
44+
)
45+
nb.config.NUMBA_BOUNDSCHECK = 1 # checks bounds errors of vectors
46+
nb.config.NUMBA_COLOR_SCHEME = (
47+
"dark_bg" # prints error messages for dark background terminals
48+
)
49+
nb.config.NUMBA_DEBUG_NRT = 1 # Numba run time (NRT) statistics counter
50+
nb.config.NUMBA_DEBUG_TYPEINFER = (
51+
1 # print out debugging information about type inference.
52+
)
53+
nb.config.NUMBA_ENABLE_PROFILING = 1 # enables profiler use
54+
nb.config.NUMBA_DUMP_CFG = 1 # prints out a control flow diagram
55+
nb.config.NUMBA_OPT = 0 # forums un optimized code from compilers
56+
nb.config.NUMBA_DEBUGINFO = 1 #
57+
nb.config.NUMBA_EXTEND_VARIABLE_LIFETIMES = (
58+
1 # allows for inspection of numba variables after end of compilation
59+
)
60+
61+
# file="str.txt";file1="list.txt"
62+
# out=sys.stdout
63+
# sys.stdout=open('debug_numba_config.txt','w')
64+
# help(nb.config)
65+
# sys.stdout.close
66+
67+
# print_msg('>> Numba config exported to debug_numba_config.txt')
68+
69+
# elif mode == "numba x86":
70+
# nb.config.NUMBA_OPT = 3
71+
# NUMBA_DISABLE_INTEL_SVML
2372

2473
import h5py
2574
import numpy as np

mcdc/print_.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import numpy as np
33
import sys
44
from mpi4py import MPI
5-
5+
from colorama import Fore, Back, Style
66

77
master = MPI.COMM_WORLD.Get_rank() == 0
88

@@ -21,7 +21,8 @@ def print_error(msg):
2121

2222
def print_warning(msg):
2323
if master:
24-
print("Warning: %s\n" % msg)
24+
print(Fore.RED + "Warning: %s\n" % msg)
25+
print(Style.RESET_ALL)
2526
sys.stdout.flush()
2627

2728

mcdc/visualizer.py

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from mcdc.print_ import print_warning
2+
13
try:
24
# launches visualization window
35
# must be inside this loop so it doesn't launch when the visualizer is imported
@@ -7,16 +9,8 @@
79
import distinctipy # creates unlimited visually distinct colors for visualization
810

911
except ImportError as e:
10-
print("")
11-
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
12-
print("MC/DC visualization error:")
13-
print(" Dependencies for visualization not installed")
14-
print(" To install optional dependencies needed for visualization:")
15-
print(" <pip install mcdc[viz]> ")
16-
print("")
17-
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
18-
print("")
19-
12+
msg = "\n >> MC/DC visualization error: \n >> dependencies for visualization not installed \n >> install optional dependencies needed for visualization with \n >> <pip install mcdc[viz]> (add para for mac)"
13+
print_warning(msg)
2014

2115
import tkinter as tk # Tkinter is used to create the window for the time slider and color key
2216
import math
@@ -420,15 +414,8 @@ def visualize(start_time=0, end_time=0, tick_interval=1, material_colors={}):
420414
# must be inside this loop so it doesn't launch when the visualizer is imported
421415
import netgen.gui
422416
except ImportError as e:
423-
print("")
424-
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
425-
print("MC/DC visualization error:")
426-
print(" Dependencies for visualization not installed")
427-
print(" To install optional dependencies needed for visualization:")
428-
print(" <pip install mcdc[viz]> ")
429-
print("")
430-
print(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
431-
print("")
417+
msg = "\n >> MC/DC visualization error: \n >> dependencies for visualization not installed \n >> install optional dependencies needed for visualization with \n >> <pip install mcdc[viz]> (add para for mac)"
418+
print_warning(msg)
432419

433420
color_key_dic = draw_Geometry(
434421
current_time=0,

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ authors = [
1818
]
1919
description = "Monte Carlo / Dynamic Code, a pure python high performance Monte Carlo neutronics package"
2020
readme = "README.md"
21-
requires-python = ">=3.9, <=3.11.7"
21+
requires-python = ">=3.9, <=3.11.8"
2222
license = {file = "LICENSE"}
2323
keywords = ["Monte Carlo", "Nuclear", "GPU", "numba", "mpi4py", "neutron transport", "neutronics", "HPC"]
2424
classifiers = [

0 commit comments

Comments
 (0)