Things to do & not to do
- Do not re-export symbols (ie from
__init__.py), always import from the original module. - Avoid star imports (
from x import *), they break type checking and IDE support. - Avoid defining
__init__.pyunless strictly necessary (it can easily introduce circular imports).
- Prefer
numpyfunctions over operators when possible (they may offer better numerical precision). - Do not create arrays using
np.ndarray(), use explicit initializers such asnp.zeros(),np.ones(),np.arange(), ornp.empty(). - Avoid magic numbers in
np.transpose(ary, format), useformat_transpose(ary, src, dst)instead.
- Cython's
.pyxcan be included anywhere, but must be accompanied by a.pyityping interface.
- Each CUDA kernel must have a unique name, duplicate names will cause incorrect kernel resolution.
- Use
pydtnn.utils.random(or a local instance) for random number generation, other generators are not multi-thread aware.
- Test all changes across backends (CPU, GPU, etc.), changes in base classes may introduce backend-specific issues.
- When comparing outputs between layers or models, always copy outputs before passing them to the next layer, some layers perform in-place operations.
- Keep
README.md,utils/parser.pyandmodel/base.pyin sync, any change in options must be reflected in all of them.
- Use
from __future__ import annotationsinstead of string type annotations, it is more legible and will be default moving forward. - Use
x | Noneinstead ofOptional[x]for type annotations, it is equivalent and will be default moving forward. - Keep
Makefileandpyproject.tomlin sync, any changes in dependencies versions must be reflected in both.
- When components structure changes, update the
Structuresection of this document accordingly. - When the Model or Dataset components structure changes, update the class's
__init__diagram.
Things you should keep in mind
- In components,
__init__is used for model-agnostic configuration, and_model_initfor model specific configuration, and_post_initand resource allocation. - When using componentes with backends, when initialized (via
_init_backend) the instance will reset, so no modifications (such as withsetattr) will be visible.
--use-gpudirectmoves data from CPU (ndarray) to GPU (GPUArray), requiresenable-cudnn--use-ncclmoves reductions from CPU (MPI) to GPU (NCCL), requiresenable-gpudirect
--enable-encryptionrequiresNCCLto be disabled (otherwise it will be skipped), typically requires--no-use-mpi-buffers(crypto libraries usually do not expose buffer access) and--use-blocking-mpi(MPI likempi4pydoes not support async object reductions)
- Shared interface and typing code can be defined in
.pydfiles. - Multiple Cython optimizations are enabled by default, check for them in
setup.py, and if desired disabled them locally with@cython.{option}(value).
- When using
PreallocMemory, temporary memory in block layers will overlap its child layers, therefore it may be overwritten.
- When using
condaandpip installfails withno such option: --config-settings, deactivate all environments and reactivate only the target environment.
- When sure, you can disable typing errors with
# pyright: ignore[{error,...}] (reason). - When sure, you can disable styling errors with
# noqa: {error,...} (reason).
How is the project organized
├── README.md
├── CONTRIBUTING.md
├── Makefile
├── pyproject.toml
├── setup.py
├── .editor
├── .mailmap
├── LICENSE
├── # other resources
├── pydtnn
│ ├── __main__.py
│ ├── __init__.py
│ ├── logging.yaml
│ ├── model
│ │ ├── __init__.py # usable models
│ │ ├── base.py # typing interface
│ │ ├── utils.py # utility methods
│ │ ├── layers.py # layers management
│ │ ├── state.py # state management
│ │ ├── init.py # initialization
│ │ ├── sync.py # synchronization
│ │ ├── repr.py # representation
│ │ ├── eval.py # model inference
│ │ └── train.py # model training
| ├── abstract
| | ├── base.py # every component
│ │ └── layerable.py # layer-like component
│ ├── activations
│ │ ├── activation.py # base
│ │ └── # each implementation
│ ├── models
│ │ ├── # each description
│ ├── layers
│ │ ├── abstract # shared
│ │ ├── layer.py # base
│ │ └── # each implementation
│ ├── losses
│ │ ├── loss.py # base
│ │ └── # each implementation
│ ├── metrics
│ │ ├── metric.py # base
│ │ └── # each implementation
│ ├── schedulers
│ │ ├── scheduler.py # base
│ │ └── # each implementation
│ ├── optimizers
│ │ ├── optimizer.py # base
│ │ └── # each implementation
│ ├── backends
│ │ ├── __init__.py # base
│ │ ├── # each implementation with whole components structure
│ │ ├── cython
│ │ │ ├── # implementation
│ │ │ └── utils
│ │ │ ├── # pyx & pyi files
│ │ │ ├── base.pyi # shared py interface
│ │ │ └── base.pyd # shared pyx interface
│ │ └── pycuda
│ │ ├── # implementation
│ │ └── utils
│ │ ├── # cu files
│ │ ├── memory_allocation.py
│ │ └── tensor_array.py
│ ├── datasets
│ │ ├── __init__.py # usable datasets
│ │ ├── abstract
│ │ │ ├── base.py # typing interface
│ │ │ ├── utils.py # utility methods
│ │ │ ├── state.py # state management
│ │ │ ├── init.py # initialization
│ │ │ ├── repr.py # representation
│ │ │ └── transform.py # transformations
│ │ ├── archive.py
│ │ ├── memory.py
│ │ ├── folder.py
│ │ ├── synthetic.py
│ │ └── # each implementation
│ ├── tracers
│ │ ├── events.py
│ │ ├── tracer.py
│ │ └── # each implementation
│ ├── tests
│ │ ├── README.md
│ │ ├── groups # test groupings
│ │ └── abstract # base test cases
│ ├── converters
│ │ ├── README.md
│ │ ├── onnx2pydtnn
│ │ ├── pydtnn2onnx
│ │ └── pytorch2pydtnn
│ ├── libs
│ │ ├── # bindings to libraries
│ │ └── utils.py
│ └── utils
│ ├── parser.py
│ ├── constants.py
│ ├── initializers.py
│ ├── debug.py
│ ├── gpu.py
│ ├── memory_pool.py
│ ├── pmlib.py
│ ├── profiler.py
│ ├── random.py
│ ├── tensor.py
│ └── # other utilities
├── scripts
│ ├── README.md
│ ├── models
│ ├── datasets
│ ├── extrae
│ ├── profilers
│ ├── tests
│ └── utils
├── vendor
│ ├── README.md
│ └── # each repository
└── datasets
└── # each dataset
Things to do
- Skip
biasandvelocityreservation when unused - Migrate
libs/{cuda,cudadrv,cudart}tocuda-bindings(and/ornvidia-cuda-runtime-cu12) - Migrate
libs/nccltonvidia-nccl-cu12 - Migrate
libs/cudnntonvidia-cudnn-cu12 - Migrate
libs/cublastonvidia-cublas-cu12 - Add PyCUDA parameter quantization (operate on
model.dtype, weights onmodel.param_dtype) - Add cuDNN graph backend
- Fix NLP support
- Add model tensor parallelism (previously implemented on a prototype)
Acquire their dependencies, build them and install them with:
export $(make env | xargs)
make deps build installFor specific dependencies, prefix the target with their name, for example:
make blis-installNote: make *-deps uses Debian-based package names
Do things work?
make testNote: exhaustive tests are skipped
python -m unittest pydtnn.tests.${TEST_FILE}.${TEST_CLASS}.${TEST_METHOD}Note: include -v for verbose mode
python -m unittest pydtnn.tests.conv_2d_cython.Conv2DCythonTestCase
mpirun python -m unittest pydtnn.tests.conv_2d_conv_gemm_long.Conv2DConvGemmLongTestCase.test_forward_backward_multiple_paramspython -m unittest pydtnn.tests.model_gpuMaking things public
make format lint
git commit -am cleanup
git pushmake build testtwine upload ./build/pydtnn/pydtnn-*