This guide covers how to extend FTorch, contribute code, and the standards expected for submissions.
Development tools for pre-processing, code styling etc. are pip-installable using the requirements-dev file:
pip install -r requirements-dev.txt
In order to streamline the process of uploading we provide a pre-commit hook in
.githooks/pre-commit.
This will check that both the .fypp and .F90 files have been updated together in a
synchronous fashion before a commmit can take place
(see below).
Use of the hook is not automatic and needs to be enabled by the developer
(after they have inspected it and are happy with its contents).
Hooks can be enabled by placing them in the .git directory with the following commands:
cp .githooks/pre-commit .git/hooks/
chmod +x .git/hooks/pre-commit
If you wish to add Torch functionality from the C++ API to the FTorch Fortran API the steps are generally as follows:
ctorch.cpp to create a C++ version of the function that accesses torch::<item>.ctorch.hftorch.fypp to create a Fortran version of the function
that binds to the version in ctorch.cpp.Refer to the LibTorch C++ Documentation and C++ API documentation for details of the available functions.
The following guidelines should be followed whilst writing new routines:
torch::Error and std::exception in the C++ functions by catching and
printing to screen before exiting cleanly.The Fortran source code in src/ftorch.F90 should not be edited directly
but instead generated from src/ftorch.fypp by running the
Fypp preprocessor.
This is done to simplify the process of overloading functions for multiple data
Fypp can be installed with the developer requirements.
To generate the Fortran code run:
fypp src/ftorch.fypp src/ftorch.F90
Conformance of these files is checked using GitHub continuous integration and the provided pre-commit hook.
Note
Generally it would be advisable to provide only the .fypp source code to
reduce duplication and confusion. However, because it is a relatively small file
and many of our users wish to "clone-and-go" rather than develop, we provide both.
Development should only take place in ftorch.fypp, however._
GPU device-specific code is handled in FTorch using codes defined in the root
CMakeLists.txt file:
set(GPU_DEVICE_NONE 0)
set(GPU_DEVICE_CUDA 1)
set(GPU_DEVICE_XPU 12)
set(GPU_DEVICE_MPS 13)
These are chosen to be consistent with the numbering used in PyTorch.
When a user specifies -DGPU_DEVICE=XPU (for example) in the FTorch CMake build, this
is mapped to the appropriate device code (in this case 12). Device codes
are passed to the C++ compiler in the following step:
target_compile_definitions(
${LIB_NAME}
PRIVATE GPU_DEVICE=${GPU_DEVICE_CODE}
GPU_DEVICE_NONE=${GPU_DEVICE_NONE} GPU_DEVICE_CUDA=${GPU_DEVICE_CUDA}
GPU_DEVICE_XPU=${GPU_DEVICE_XPU} GPU_DEVICE_MPS=${GPU_DEVICE_MPS})
The chosen device code will enable the appropriate C pre-processor conditions in the C++ source so that that the code relevant to that device type becomes active.
An example illustrating why this approach was taken is that if we removed the
device codes and pre-processor conditions and tried to build with a CPU-only or
CUDA LibTorch installation then compile errors would arise from the use of the
torch::xpu module in src/ctorch.cpp.
Note
The HIP/ROCm backend uses the same API as the CUDA backend, so FTorch treats HIP as CUDA in places when calling LibTorch or PyTorch. This should not concern end-users as the FTorch and pt2ts.py APIs handle this. For further information see the PyTorch HIP documentation
Contributions for new features, bugfixes, or improvements should be raised in a pull request.
In addition to making code contributions as described above users should also include documentation, in-code and written if required, and tests to cover any changes/additions. Guidance on testing can be found on the testing page. Notable changes should also be documented in the Changelog.
FTorch source code is subject to a number of static analysis checks to ensure that it conforms to quality and legibility. These tools are a mixture of formatters and linters.
The tools we use are as follows on a language-by-language basis:
Instructions on using these tools can be found in their respective documentations. Note that all but ShellCheck may be installed with pip as described in the developer requirements.
Contributors should run these tools over their code and ensure that it conforms before submitting a pull request. If there is a good reason to ignore a particular rule this should be justified in the pull request and ideally documented in the code. There is a GitHub action as part of the continuous integration that will perform these checks on all pull requests.
The documentation for FTorch is generated using FORD which is installed as part of the developer requirements. This builds API documentation based off of in-code docstring syntax, and web-based documentation from markdown pages. For detailed information refer to the FORD User Guide.
To generate the documentation run:
ford FTorch.md
from the root of the repository.
FORD uses graphviz to generate dependency graphs from the Fortran source code1. For this, you will need to install it on your system - see the installation guide for your platform.
Ford makes use of a docstring syntax for annotating code. As a quick-start:
!! is used to signify documentation.!>.The following examples from FORD and FTorch show this in context:
subroutine feed_pets(cats, dogs, food)
!! Feeds your cats and dogs, if enough food is available.
! Arguments
integer, intent(in) :: cats !! The number of cats.
integer, intent(in) :: dogs !! The number of dogs.
real, intent(inout) :: food
!! The ammount of pet food (in kilograms) which you have on hand.
!...
end subroutine feed_pets
!> Type for holding a torch neural net (nn.Module).
type torch_model
type(c_ptr) :: p = c_null_ptr !! pointer to the neural net in memory
end type torch_model
Documentation of the C/C++ functions is provided
by Doxygen.
This should be included in the header file ctorch.h.
FTorch.md is the FORD index file that contains project metadata and describes
the project homepage.
Additional pages are contained in pages/ as markdown files.
Notes:
ftorch.F90
via the C preprocessor in FTorch.md to match those in the CMakeLists.txt.dbg: true in FTorch.md to allow
FORD to continue when encountering errors. Note that in this case the documentation
may build but be incomplete.graph: false in FTorch.md whilst prototyping
to skip the time-consuming generation of dependency graphs.FTorch has follows semantic versioning.
The project version should be updated accordingly through the PACKAGE_VERSION in
CMakeLists.txt for each new release.
A log of notable changes to the software is kept in CHANGELOG.md.
This follows the conventions of Keep a Changelog and should
be updated by contributors and maintainers as part of a pull request when appropriate.
Note
"Notable" includes new features, bugfixes, dependency updates etc.
"Notable" does not cover typo corrections, documentation rephrasing and restyling, or correction of other minor infelicities that do not impact the user or developer.
New minor releases are made when deemed appropriate by maintainers by adding a tag to the commit and creating a corresponding GitHub Release. The minor number of the version should be incremented, the entry for the version finalised in the changelog, and a clean log for 'Unreleased' changes created.
New patch releases are made whenever a bugfix is merged. The patch number of the version should be incremented, a tag attached to the commit, and a note made under the current 'Unreleased' patches header in the changelog.
Note: If FORD cannot locate the graphviz executable (it is not a hard dependency) it will generate a warning. ↩