twincher 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- twincher-0.1.0/.gitignore +32 -0
- twincher-0.1.0/CHANGELOG.md +18 -0
- twincher-0.1.0/CITATION.cff +33 -0
- twincher-0.1.0/CLA.md +71 -0
- twincher-0.1.0/CMakeLists.txt +138 -0
- twincher-0.1.0/CONTRIBUTING.md +133 -0
- twincher-0.1.0/LICENSE +661 -0
- twincher-0.1.0/PKG-INFO +113 -0
- twincher-0.1.0/README.md +592 -0
- twincher-0.1.0/benchmarks/bench_cpu.cpp +98 -0
- twincher-0.1.0/benchmarks/perf.py +239 -0
- twincher-0.1.0/docs/pypi_description.md +76 -0
- twincher-0.1.0/include/common.h +261 -0
- twincher-0.1.0/include/shuttle_cpu.h +273 -0
- twincher-0.1.0/include/shuttle_gpu.hpp +117 -0
- twincher-0.1.0/include/shuttle_util.h +128 -0
- twincher-0.1.0/include/twinch.h +299 -0
- twincher-0.1.0/include/twincher.h +157 -0
- twincher-0.1.0/pyproject.toml +73 -0
- twincher-0.1.0/python/twincher/__init__.py +51 -0
- twincher-0.1.0/python/twincher/hs_loss.py +185 -0
- twincher-0.1.0/python/twincher/hs_monitor_p2.py +124 -0
- twincher-0.1.0/python/twincher/hs_noise_loss.py +165 -0
- twincher-0.1.0/python/twincher/hs_solver.py +209 -0
- twincher-0.1.0/python/twincher/hs_twincher.py +34 -0
- twincher-0.1.0/python/twincher/interpolator.py +329 -0
- twincher-0.1.0/python/twincher/learner.py +362 -0
- twincher-0.1.0/python/twincher/learning_curve.py +101 -0
- twincher-0.1.0/python/twincher/monitor.py +19 -0
- twincher-0.1.0/python/twincher/noise_check.py +100 -0
- twincher-0.1.0/python/twincher/registry.py +42 -0
- twincher-0.1.0/python/twincher/shuttle.py +326 -0
- twincher-0.1.0/python/twincher/solver.py +57 -0
- twincher-0.1.0/python/twincher/time_monitor.py +313 -0
- twincher-0.1.0/python/twincher/tw_util.py +235 -0
- twincher-0.1.0/python/twincher/verifier.py +143 -0
- twincher-0.1.0/src/bindings.cpp +108 -0
- twincher-0.1.0/src/common.cpp +30 -0
- twincher-0.1.0/src/shuttle_gpu.cu +331 -0
- twincher-0.1.0/tests/conftest.py +42 -0
- twincher-0.1.0/tests/helpers.py +57 -0
- twincher-0.1.0/tests/test_core.py +379 -0
- twincher-0.1.0/tests/test_e2e_spiral.py +92 -0
- twincher-0.1.0/tests/test_errors.py +86 -0
- twincher-0.1.0/tests/test_file_format.py +98 -0
- twincher-0.1.0/tests/test_learner.py +118 -0
- twincher-0.1.0/tests/test_package.py +106 -0
- twincher-0.1.0/tests/test_shuttle.py +122 -0
- twincher-0.1.0/tutorial/README.md +48 -0
- twincher-0.1.0/tutorial/double_gaussian.py +94 -0
- twincher-0.1.0/tutorial/output_tools_p1_y2.py +138 -0
- twincher-0.1.0/tutorial/output_tools_p2.py +46 -0
- twincher-0.1.0/tutorial/spiral.py +59 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Build artifacts
|
|
2
|
+
/build/
|
|
3
|
+
/dist/
|
|
4
|
+
/wheelhouse/
|
|
5
|
+
*.egg-info/
|
|
6
|
+
CMakeCache.txt
|
|
7
|
+
CMakeFiles/
|
|
8
|
+
cmake_install.cmake
|
|
9
|
+
*.o
|
|
10
|
+
*.a
|
|
11
|
+
*.so
|
|
12
|
+
|
|
13
|
+
# Python
|
|
14
|
+
__pycache__/
|
|
15
|
+
*.py[cod]
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.nox/
|
|
20
|
+
.ruff_cache/
|
|
21
|
+
.mypy_cache/
|
|
22
|
+
|
|
23
|
+
# Outputs of tutorials, tests and benchmarks
|
|
24
|
+
/tutorial/output_*/
|
|
25
|
+
twincher_output/
|
|
26
|
+
*.twc
|
|
27
|
+
*.tw
|
|
28
|
+
|
|
29
|
+
# Editors and OS
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
.DS_Store
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2026-10-02
|
|
6
|
+
|
|
7
|
+
First public release.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Computational core in C++ with a CPU backend (OpenMP) and an optional GPU backend (CUDA), accessible through `twincher.Shuttle`. It supports PyTorch tensors, NumPy arrays and CuPy arrays.
|
|
12
|
+
- The hyper-sail architecture (`hs`): loss terms `HSLoss` and `HSNoiseLoss`, solver `HSSolver` and monitor `HSMonitorP2`.
|
|
13
|
+
- Training and evaluation: `Learner`, `solver()`, `Verifier`, `noise_check()`, `monitor()` and `TimeMonitor`.
|
|
14
|
+
- A registry for adding architectures (`register()`).
|
|
15
|
+
- File format for trained twinchers (`.twc`) with a format version.
|
|
16
|
+
- Tutorials: spiral and double Gaussian.
|
|
17
|
+
|
|
18
|
+
[0.1.0]: https://github.com/arkady-gonoskov/twincher/releases/tag/v0.1.0
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use this software, please cite the article below."
|
|
3
|
+
title: "twincher"
|
|
4
|
+
type: software
|
|
5
|
+
abstract: >-
|
|
6
|
+
Python package with a C++/CUDA core that implements twinchers: trainable
|
|
7
|
+
diffeomorphic representations for fast, never-stalling solution of inverse
|
|
8
|
+
problems.
|
|
9
|
+
authors:
|
|
10
|
+
- family-names: Gonoskov
|
|
11
|
+
given-names: Arkady
|
|
12
|
+
email: contact@twincher.ai
|
|
13
|
+
version: 0.1.0
|
|
14
|
+
date-released: 2026-10-02
|
|
15
|
+
license: AGPL-3.0-only
|
|
16
|
+
url: "https://www.twincher.ai"
|
|
17
|
+
repository-code: "https://github.com/arkady-gonoskov/twincher"
|
|
18
|
+
keywords:
|
|
19
|
+
- inverse problems
|
|
20
|
+
- diffeomorphism
|
|
21
|
+
- representation learning
|
|
22
|
+
- machine learning
|
|
23
|
+
preferred-citation:
|
|
24
|
+
type: article
|
|
25
|
+
title: "Twincher: Bijective Representation Learning for Robust Inversion of Continuous Systems"
|
|
26
|
+
authors:
|
|
27
|
+
- family-names: Gonoskov
|
|
28
|
+
given-names: Arkady
|
|
29
|
+
journal: "arXiv preprint arXiv:2605.13470"
|
|
30
|
+
year: 2026
|
|
31
|
+
month: 5
|
|
32
|
+
doi: "10.48550/arXiv.2605.13470"
|
|
33
|
+
url: "https://arxiv.org/abs/2605.13470"
|
twincher-0.1.0/CLA.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Twincher Contributor License Agreement
|
|
2
|
+
|
|
3
|
+
Version 1.0
|
|
4
|
+
|
|
5
|
+
Thank you for your interest in contributing to Twincher. Twincher is distributed under the GNU Affero General Public License, version 3 (AGPL-3.0). It is also available under separate commercial licenses. So that contributions can be distributed on both of these terms, the Project Owner asks all contributors to accept this Contributor License Agreement (the "Agreement"). Under this Agreement you keep the copyright in your Contributions. You grant the Project Owner a license to use them, as described below.
|
|
6
|
+
|
|
7
|
+
Please read this Agreement carefully. It applies both to individuals and to legal entities (such as companies) that contribute to the Project.
|
|
8
|
+
|
|
9
|
+
## 1. Definitions
|
|
10
|
+
|
|
11
|
+
**"Project Owner"** means Arkady Gonoskov, together with his successors and assigns. This includes any legal entity to which the rights in the Project are transferred.
|
|
12
|
+
|
|
13
|
+
**"Project"** means the software, documentation and other materials known as Twincher that are owned and managed by the Project Owner, including their source code repositories.
|
|
14
|
+
|
|
15
|
+
**"You"** (or **"Your"**) means the individual or legal entity that accepts this Agreement. For legal entities, "You" includes the entity and all other entities that control it, are controlled by it, or are under common control with it. For this definition, "control" means ownership of more than fifty percent (50%) of the voting securities or other ownership interests, or the power to direct the management and policies of the entity.
|
|
16
|
+
|
|
17
|
+
**"Contribution"** means any original work of authorship that You submit to the Project Owner for inclusion in the Project, including any modifications of or additions to existing work. "Submit" means any form of electronic or written communication sent to the Project Owner or its representatives. Examples include pull requests, patches, issues and discussions in the Project's repositories, as well as e-mail. It does not include communication that You conspicuously mark, or otherwise designate in writing, as "Not a Contribution".
|
|
18
|
+
|
|
19
|
+
## 2. Copyright license
|
|
20
|
+
|
|
21
|
+
You grant to the Project Owner, and to recipients of software distributed by the Project Owner, a copyright license with the following properties: perpetual, worldwide, non-exclusive, no-charge, royalty-free and irrevocable. The license allows them to reproduce, prepare derivative works of, publicly display, publicly perform, sublicense and distribute Your Contributions and such derivative works.
|
|
22
|
+
|
|
23
|
+
Such distribution and sublicensing may be under any license terms, including open source licenses as well as proprietary or commercial licenses.
|
|
24
|
+
|
|
25
|
+
## 3. Patent license
|
|
26
|
+
|
|
27
|
+
You grant to the Project Owner, and to recipients of software distributed by the Project Owner, a patent license with the following properties: perpetual, worldwide, non-exclusive, no-charge, royalty-free and irrevocable (except as stated in this section). The license allows them to make, have made, use, offer to sell, sell, import and otherwise transfer Your Contributions.
|
|
28
|
+
|
|
29
|
+
This license applies only to those patent claims licensable by You that are necessarily infringed by Your Contribution alone, or by the combination of Your Contribution with the Project to which it was submitted.
|
|
30
|
+
|
|
31
|
+
If any entity institutes patent litigation against You or any other entity (including a cross-claim or counterclaim in a lawsuit) alleging that Your Contribution, or the Project to which You contributed, constitutes direct or contributory patent infringement, then any patent licenses granted to that entity under this Agreement for that Contribution terminate as of the date such litigation is filed.
|
|
32
|
+
|
|
33
|
+
## 4. Commitment to open source availability
|
|
34
|
+
|
|
35
|
+
When the Project Owner distributes a Contribution as part of the Project, the Project Owner agrees to also make it available under the open source license or licenses under which the Project is publicly distributed on the date the Contribution was submitted. This commitment does not limit the rights granted in Sections 2 and 3.
|
|
36
|
+
|
|
37
|
+
## 5. Moral rights
|
|
38
|
+
|
|
39
|
+
To the fullest extent permitted by applicable law, You waive, and agree not to assert, any moral rights You may have in Your Contributions against the Project Owner or recipients of software distributed by the Project Owner.
|
|
40
|
+
|
|
41
|
+
## 6. Your representations
|
|
42
|
+
|
|
43
|
+
You represent that:
|
|
44
|
+
|
|
45
|
+
1. You are legally entitled to grant the licenses in this Agreement.
|
|
46
|
+
2. If Your employer, or any other party, has rights to intellectual property that You create, including Your Contributions, then one of the following is true: You have received permission to make Contributions on its behalf; that party has waived such rights for Your Contributions; or that party has accepted this Agreement.
|
|
47
|
+
3. Each of Your Contributions is Your original creation. It includes complete details of any third-party license or other restriction (including related patents and trademarks) that You are personally aware of and that is associated with any part of the Contribution.
|
|
48
|
+
4. If You wish to submit work that is not Your original creation, You will submit it separately from any Contribution. You will identify the complete details of its source and of any license or other restriction that You are personally aware of, and conspicuously mark the work as "Submitted on behalf of a third party: [named here]".
|
|
49
|
+
|
|
50
|
+
If You accept this Agreement on behalf of a legal entity, You represent that You are authorized to do so.
|
|
51
|
+
|
|
52
|
+
You agree to notify the Project Owner of any facts or circumstances of which You become aware that would make these representations inaccurate in any respect.
|
|
53
|
+
|
|
54
|
+
## 7. Retained rights
|
|
55
|
+
|
|
56
|
+
You keep all right, title and interest in Your Contributions. Apart from the licenses granted in this Agreement, You may use Your Contributions for any purpose.
|
|
57
|
+
|
|
58
|
+
## 8. No obligation and no warranty
|
|
59
|
+
|
|
60
|
+
The Project Owner is not obligated to use or include any Contribution in the Project.
|
|
61
|
+
|
|
62
|
+
You are not expected to provide support for Your Contributions, except to the extent You desire to provide support. Unless required by applicable law or agreed to in writing, You provide Your Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. This includes, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
63
|
+
|
|
64
|
+
## 9. Acceptance
|
|
65
|
+
|
|
66
|
+
You accept this Agreement in one of two ways:
|
|
67
|
+
|
|
68
|
+
- by confirming it electronically through the mechanism provided in the Project's repository, for example by a comment on a pull request; or
|
|
69
|
+
- by sending a signed copy to contact@twincher.ai.
|
|
70
|
+
|
|
71
|
+
Once accepted, this Agreement applies to all Contributions You have submitted and will submit to the Project.
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
# Copyright (C) 2025-2026 Arkady Gonoskov
|
|
3
|
+
|
|
4
|
+
# Builds the compiled core of twincher: the Python extension module twincher._core.
|
|
5
|
+
# Normally invoked through pip (scikit-build-core), see pyproject.toml and CONTRIBUTING.md.
|
|
6
|
+
|
|
7
|
+
cmake_minimum_required(VERSION 3.24)
|
|
8
|
+
|
|
9
|
+
# Compile CUDA code for the GPU(s) of the build machine unless architectures are given
|
|
10
|
+
# explicitly, e.g. via the environment variable CUDAARCHS="86;120" or
|
|
11
|
+
# -DCMAKE_CUDA_ARCHITECTURES="86;120".
|
|
12
|
+
if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES AND NOT DEFINED ENV{CUDAARCHS})
|
|
13
|
+
set(CMAKE_CUDA_ARCHITECTURES native)
|
|
14
|
+
endif()
|
|
15
|
+
|
|
16
|
+
project(twincher LANGUAGES CXX)
|
|
17
|
+
|
|
18
|
+
# GPU backend: AUTO builds it if a CUDA compiler (nvcc) is found, and otherwise builds a
|
|
19
|
+
# CPU-only package with a warning. ON makes the CUDA compiler mandatory, OFF disables it.
|
|
20
|
+
set(TWINCHER_CUDA AUTO CACHE STRING "Build the CUDA backend (AUTO, ON or OFF)")
|
|
21
|
+
set_property(CACHE TWINCHER_CUDA PROPERTY STRINGS AUTO ON OFF)
|
|
22
|
+
set(TWINCHER_WITH_CUDA OFF)
|
|
23
|
+
if(NOT TWINCHER_CUDA STREQUAL "OFF")
|
|
24
|
+
include(CheckLanguage)
|
|
25
|
+
check_language(CUDA)
|
|
26
|
+
if(CMAKE_CUDA_COMPILER)
|
|
27
|
+
enable_language(CUDA)
|
|
28
|
+
set(TWINCHER_WITH_CUDA ON)
|
|
29
|
+
elseif(TWINCHER_CUDA STREQUAL "ON")
|
|
30
|
+
message(FATAL_ERROR "TWINCHER_CUDA=ON, but no CUDA compiler (nvcc) was found.")
|
|
31
|
+
else()
|
|
32
|
+
message(WARNING
|
|
33
|
+
"No CUDA compiler (nvcc) was found: twincher is built without GPU support. "
|
|
34
|
+
"To enable it, make nvcc available (e.g. add the bin directory of the CUDA toolkit "
|
|
35
|
+
"to PATH, or set CUDACXX) and reinstall.")
|
|
36
|
+
endif()
|
|
37
|
+
endif()
|
|
38
|
+
message(STATUS "twincher: CUDA backend ${TWINCHER_WITH_CUDA}")
|
|
39
|
+
|
|
40
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
41
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
42
|
+
set(CMAKE_CUDA_STANDARD 17)
|
|
43
|
+
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
|
|
44
|
+
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
|
45
|
+
# compile_commands.json in the build directory, for code editors (IntelliSense) and tools
|
|
46
|
+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
47
|
+
|
|
48
|
+
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
49
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
|
50
|
+
endif()
|
|
51
|
+
|
|
52
|
+
option(TWINCHER_NATIVE_ARCH
|
|
53
|
+
"Optimize host code for the CPU of the build machine (-march=native); the result is not portable" OFF)
|
|
54
|
+
option(TWINCHER_BUILD_BENCHMARKS "Build C++ benchmark executables" OFF)
|
|
55
|
+
|
|
56
|
+
# Version string reported by info(); scikit-build-core provides it from pyproject.toml
|
|
57
|
+
if(DEFINED SKBUILD_PROJECT_VERSION)
|
|
58
|
+
set(TWINCHER_VERSION "${SKBUILD_PROJECT_VERSION}")
|
|
59
|
+
else()
|
|
60
|
+
set(TWINCHER_VERSION "dev")
|
|
61
|
+
endif()
|
|
62
|
+
|
|
63
|
+
if(NOT MSVC)
|
|
64
|
+
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Wall>)
|
|
65
|
+
endif()
|
|
66
|
+
if(TWINCHER_NATIVE_ARCH)
|
|
67
|
+
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-march=native>)
|
|
68
|
+
endif()
|
|
69
|
+
|
|
70
|
+
# ---------------------------------------------------------------------------------------
|
|
71
|
+
# Dependencies
|
|
72
|
+
# ---------------------------------------------------------------------------------------
|
|
73
|
+
find_package(Python 3.10 REQUIRED COMPONENTS Interpreter Development.Module)
|
|
74
|
+
if(NOT DEFINED SKBUILD AND NOT DEFINED pybind11_DIR)
|
|
75
|
+
# plain CMake build: use pybind11 installed in the active Python environment
|
|
76
|
+
execute_process(
|
|
77
|
+
COMMAND "${Python_EXECUTABLE}" -m pybind11 --cmakedir
|
|
78
|
+
OUTPUT_VARIABLE pybind11_DIR
|
|
79
|
+
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
80
|
+
ERROR_QUIET
|
|
81
|
+
)
|
|
82
|
+
endif()
|
|
83
|
+
find_package(pybind11 CONFIG REQUIRED)
|
|
84
|
+
# OpenMP parallelizes the CPU backend; without it, the CPU backend runs in a single thread
|
|
85
|
+
find_package(OpenMP COMPONENTS CXX)
|
|
86
|
+
if(NOT OpenMP_CXX_FOUND)
|
|
87
|
+
message(WARNING "OpenMP was not found: the CPU backend of twincher will run in a single thread.")
|
|
88
|
+
if(NOT MSVC)
|
|
89
|
+
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-Wno-unknown-pragmas>)
|
|
90
|
+
endif()
|
|
91
|
+
endif()
|
|
92
|
+
|
|
93
|
+
# ---------------------------------------------------------------------------------------
|
|
94
|
+
# CUDA backend (static library linked into the extension module)
|
|
95
|
+
# ---------------------------------------------------------------------------------------
|
|
96
|
+
if(TWINCHER_WITH_CUDA)
|
|
97
|
+
find_package(CUDAToolkit REQUIRED)
|
|
98
|
+
add_library(twincher_cuda STATIC src/shuttle_gpu.cu)
|
|
99
|
+
target_include_directories(twincher_cuda
|
|
100
|
+
PUBLIC ${PROJECT_SOURCE_DIR}/include
|
|
101
|
+
PRIVATE ${CUDAToolkit_INCLUDE_DIRS}/cccl
|
|
102
|
+
)
|
|
103
|
+
# The static CUDA runtime makes the module independent of the location/version of
|
|
104
|
+
# libcudart.so at run time; only the NVIDIA driver is needed.
|
|
105
|
+
target_link_libraries(twincher_cuda PUBLIC CUDA::cudart_static)
|
|
106
|
+
target_compile_definitions(twincher_cuda PUBLIC TWINCHER_WITH_CUDA)
|
|
107
|
+
set_target_properties(twincher_cuda PROPERTIES CUDA_SEPARABLE_COMPILATION OFF)
|
|
108
|
+
# Useful options for development and profiling of CUDA kernels:
|
|
109
|
+
# -lineinfo source line information for Nsight Compute
|
|
110
|
+
# -Xptxas -v report register and shared memory usage
|
|
111
|
+
# --maxrregcount=60 limit the number of registers per thread
|
|
112
|
+
# target_compile_options(twincher_cuda PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:-lineinfo>)
|
|
113
|
+
endif()
|
|
114
|
+
|
|
115
|
+
# ---------------------------------------------------------------------------------------
|
|
116
|
+
# Python extension module twincher._core
|
|
117
|
+
# ---------------------------------------------------------------------------------------
|
|
118
|
+
pybind11_add_module(_core src/bindings.cpp src/common.cpp)
|
|
119
|
+
target_include_directories(_core PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
|
120
|
+
if(OpenMP_CXX_FOUND)
|
|
121
|
+
target_link_libraries(_core PRIVATE OpenMP::OpenMP_CXX)
|
|
122
|
+
endif()
|
|
123
|
+
if(TWINCHER_WITH_CUDA)
|
|
124
|
+
target_link_libraries(_core PRIVATE twincher_cuda)
|
|
125
|
+
endif()
|
|
126
|
+
target_compile_definitions(_core PRIVATE TWINCHER_VERSION="${TWINCHER_VERSION}")
|
|
127
|
+
install(TARGETS _core LIBRARY DESTINATION twincher)
|
|
128
|
+
|
|
129
|
+
# ---------------------------------------------------------------------------------------
|
|
130
|
+
# Benchmarks (optional, not installed)
|
|
131
|
+
# ---------------------------------------------------------------------------------------
|
|
132
|
+
if(TWINCHER_BUILD_BENCHMARKS)
|
|
133
|
+
add_executable(bench_cpu benchmarks/bench_cpu.cpp)
|
|
134
|
+
target_include_directories(bench_cpu PRIVATE ${PROJECT_SOURCE_DIR}/include)
|
|
135
|
+
if(OpenMP_CXX_FOUND)
|
|
136
|
+
target_link_libraries(bench_cpu PRIVATE OpenMP::OpenMP_CXX)
|
|
137
|
+
endif()
|
|
138
|
+
endif()
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# Contributing to Twincher
|
|
2
|
+
|
|
3
|
+
Thank you for considering a contribution to Twincher! Bug reports, suggestions and pull requests are welcome.
|
|
4
|
+
|
|
5
|
+
## License and Contributor License Agreement
|
|
6
|
+
|
|
7
|
+
Twincher is distributed under the [GNU Affero General Public License, version 3](LICENSE) (AGPL-3.0). It is also available under separate commercial licenses. So that contributions can be distributed on both of these terms, every contributor needs to accept the [Contributor License Agreement](CLA.md) (CLA) before their first pull request can be merged.
|
|
8
|
+
|
|
9
|
+
The CLA is a license, not a transfer of ownership: you keep the copyright in your contributions. When you make a contribution to the Project, the Project Owner also commits to keep it available under the open source license of the Project (see Section 4 of the CLA).
|
|
10
|
+
|
|
11
|
+
You can accept the CLA in either of two ways:
|
|
12
|
+
|
|
13
|
+
- **Individuals:** confirm it in a comment on your pull request, when asked to do so.
|
|
14
|
+
- **Companies and other organizations:** send a signed copy to contact@twincher.ai.
|
|
15
|
+
|
|
16
|
+
If you contribute as part of your job, please make sure your employer agrees. Your employer may need to accept the CLA as an organization.
|
|
17
|
+
|
|
18
|
+
## Development setup
|
|
19
|
+
|
|
20
|
+
Requirements:
|
|
21
|
+
|
|
22
|
+
- Linux (or WSL);
|
|
23
|
+
- Python >= 3.10;
|
|
24
|
+
- a C++17 compiler with OpenMP support;
|
|
25
|
+
- for the GPU backend, the CUDA toolkit (`nvcc`).
|
|
26
|
+
|
|
27
|
+
CMake and Ninja are installed into the virtual environment below.
|
|
28
|
+
|
|
29
|
+
Create a virtual environment and install the build tools into it:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python -m venv .venv
|
|
33
|
+
source .venv/bin/activate
|
|
34
|
+
pip install scikit-build-core pybind11 cmake ninja
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then install twincher in editable mode:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install --no-build-isolation -Ceditable.rebuild=true -Cbuild-dir=build/editable -e ".[dev]"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
In this mode, the Python sources are used directly from `python/twincher`. After you change the C++/CUDA sources, the extension module is rebuilt automatically at the next `import twincher`. The build files are kept in `build/editable`, so rebuilds are incremental.
|
|
44
|
+
|
|
45
|
+
### Running the tests
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
python -m pytest # all tests (about one minute)
|
|
49
|
+
python -m pytest -m "not e2e" # unit tests only (a few seconds)
|
|
50
|
+
python -m pytest -rP tests/test_core.py # also show the values printed by the tests
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The tests use the installed package, so they can be run from any environment in which twincher is installed.
|
|
54
|
+
|
|
55
|
+
Tests that need a GPU are marked with `gpu`. They are skipped automatically if twincher cannot use a GPU: either there is none, or twincher was built without CUDA. The GPU tests with CuPy arrays are additionally skipped if CuPy is not installed (`pip install cupy-cuda13x`, matching your version of CUDA).
|
|
56
|
+
|
|
57
|
+
| Tests | Content |
|
|
58
|
+
|---|---|
|
|
59
|
+
| `test_core.py` | The computational core: CPU against finite differences, GPU against CPU |
|
|
60
|
+
| `test_shuttle.py`, `test_errors.py`, `test_file_format.py` | The Python wrapper `Shuttle`, error handling, `.twc` files |
|
|
61
|
+
| `test_learner.py`, `test_package.py` | `Learner`, solver and `Verifier` on a tiny problem; imports, registry, utilities |
|
|
62
|
+
| `test_e2e_spiral.py` | End-to-end (marked `e2e`): training on the spiral problem and solving the inverse problem |
|
|
63
|
+
|
|
64
|
+
### Continuous integration
|
|
65
|
+
|
|
66
|
+
For every push to `main` and every pull request, GitHub Actions ([.github/workflows/tests.yml](.github/workflows/tests.yml)) runs three jobs:
|
|
67
|
+
|
|
68
|
+
- **Tests:** on Python 3.10 to 3.14, with the CPU-only package.
|
|
69
|
+
- **CUDA build:** compiles the CUDA backend in a container with the CUDA toolkit.
|
|
70
|
+
- **Source distribution:** builds the source distribution and tests the package installed from it.
|
|
71
|
+
|
|
72
|
+
The runners of GitHub have no GPU, so the GPU tests are not run there. Please run the tests on a machine with a GPU before submitting changes of the C++/CUDA core.
|
|
73
|
+
|
|
74
|
+
The workflow [.github/workflows/release.yml](.github/workflows/release.yml) publishes releases, see [Releasing](#releasing).
|
|
75
|
+
|
|
76
|
+
### Documentation
|
|
77
|
+
|
|
78
|
+
- [README.md](README.md) is the main documentation, shown on GitHub. Formulas are written as ```` ```math ```` blocks and inline as `` $`...`$ ``: GitHub passes these to MathJax unchanged, whereas `$...$` and `$$...$$` are subject to Markdown processing (backslashes and underscores are lost).
|
|
79
|
+
- [docs/pypi_description.md](docs/pypi_description.md) is the text of the package page on PyPI, which cannot render formulas and the images of the README. Its example is the same as in the section "Getting started" of the README; please keep them in sync.
|
|
80
|
+
- [CHANGELOG.md](CHANGELOG.md) lists notable changes for each release.
|
|
81
|
+
|
|
82
|
+
### Plain CMake build (C++ benchmarks)
|
|
83
|
+
|
|
84
|
+
With the virtual environment activated:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
cmake -S . -B build/cmake -G Ninja -DTWINCHER_BUILD_BENCHMARKS=ON
|
|
88
|
+
cmake --build build/cmake
|
|
89
|
+
build/cmake/bench_cpu 0 6 # mode 0 (inference), 6 threads
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Build options
|
|
93
|
+
|
|
94
|
+
The following CMake options can be passed to pip as `-Ccmake.define.<OPTION>=<VALUE>`:
|
|
95
|
+
|
|
96
|
+
| Option | Default | Meaning |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| `TWINCHER_CUDA` | `AUTO` | GPU backend. `AUTO`: build it if a CUDA compiler (nvcc) is found, otherwise build CPU-only with a warning. `ON`: require it. `OFF`: disable it. |
|
|
99
|
+
| `CMAKE_CUDA_ARCHITECTURES` | `native` | GPU architectures to compile for, e.g. `"86;120"`. The environment variable `CUDAARCHS` can be used instead. |
|
|
100
|
+
| `TWINCHER_NATIVE_ARCH` | `OFF` | Optimize host code for the CPU of the build machine (`-march=native`). The result is not portable. |
|
|
101
|
+
| `TWINCHER_BUILD_BENCHMARKS` | `OFF` | Build the C++ benchmark executables. |
|
|
102
|
+
|
|
103
|
+
### Building distributions
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
pip install build
|
|
107
|
+
python -m build # creates dist/twincher-<version>.tar.gz and a wheel
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Releasing
|
|
111
|
+
|
|
112
|
+
Releases are published on PyPI as source distributions by the workflow [.github/workflows/release.yml](.github/workflows/release.yml), using trusted publishing (no API tokens).
|
|
113
|
+
|
|
114
|
+
### For each release
|
|
115
|
+
|
|
116
|
+
1. Make sure that the tests pass on GitHub (workflow *Tests*) and locally on a machine with a GPU (`python -m pytest`).
|
|
117
|
+
2. Set the new version in `pyproject.toml` and `CITATION.cff` (also `date-released`), and move the changes in `CHANGELOG.md` under a heading with the version and date. Commit and push to `main`.
|
|
118
|
+
3. Optionally, make a trial run on TestPyPI: in the *Actions* tab, run the workflow *Release* manually. Then install from TestPyPI in a new environment:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple/ twincher
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
TestPyPI, like PyPI, accepts each version only once; for repeated trials use pre-release versions such as `0.2.0rc1`.
|
|
125
|
+
4. Create a release on GitHub with the tag `v<version>` (for example `v0.1.0`), with the changes from `CHANGELOG.md` as description. Publishing the release starts the upload to PyPI.
|
|
126
|
+
|
|
127
|
+
## Reporting issues
|
|
128
|
+
|
|
129
|
+
When reporting a bug, please include:
|
|
130
|
+
|
|
131
|
+
- the Twincher version (`python -c "import twincher; print(twincher.__version__)"`);
|
|
132
|
+
- your operating system, Python version, and CUDA version (if relevant);
|
|
133
|
+
- a minimal script that reproduces the problem.
|