idun 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.
Files changed (64) hide show
  1. idun-0.1.0/CMakeLists.txt +39 -0
  2. idun-0.1.0/CMakePresets.json +27 -0
  3. idun-0.1.0/LICENSE +202 -0
  4. idun-0.1.0/NOTICE +39 -0
  5. idun-0.1.0/PKG-INFO +90 -0
  6. idun-0.1.0/README.md +66 -0
  7. idun-0.1.0/native/include/idun_metal.h +111 -0
  8. idun-0.1.0/native/metal/idun_metal.mm +373 -0
  9. idun-0.1.0/pyproject.toml +63 -0
  10. idun-0.1.0/src/idun/__init__.py +11 -0
  11. idun-0.1.0/src/idun/_jit.py +33 -0
  12. idun-0.1.0/src/idun/_version.py +3 -0
  13. idun-0.1.0/src/idun/base.py +127 -0
  14. idun-0.1.0/src/idun/data/__init__.py +12 -0
  15. idun-0.1.0/src/idun/data/binning.py +74 -0
  16. idun-0.1.0/src/idun/data/dataset.py +130 -0
  17. idun-0.1.0/src/idun/data/layout.py +86 -0
  18. idun-0.1.0/src/idun/data/manifest.py +68 -0
  19. idun-0.1.0/src/idun/data/refits.py +17 -0
  20. idun-0.1.0/src/idun/data/writer.py +202 -0
  21. idun-0.1.0/src/idun/dataset.py +305 -0
  22. idun-0.1.0/src/idun/errors.py +37 -0
  23. idun-0.1.0/src/idun/gbm/__init__.py +14 -0
  24. idun-0.1.0/src/idun/gbm/backends/__init__.py +42 -0
  25. idun-0.1.0/src/idun/gbm/backends/base.py +215 -0
  26. idun-0.1.0/src/idun/gbm/backends/cpu.py +504 -0
  27. idun-0.1.0/src/idun/gbm/backends/metal.py +917 -0
  28. idun-0.1.0/src/idun/gbm/booster.py +173 -0
  29. idun-0.1.0/src/idun/gbm/estimator.py +168 -0
  30. idun-0.1.0/src/idun/gbm/features.py +82 -0
  31. idun-0.1.0/src/idun/gbm/kernels/metal/gbm.metal +921 -0
  32. idun-0.1.0/src/idun/gbm/multi.py +274 -0
  33. idun-0.1.0/src/idun/gbm/objective.py +19 -0
  34. idun-0.1.0/src/idun/gbm/params.py +109 -0
  35. idun-0.1.0/src/idun/gbm/sampling.py +41 -0
  36. idun-0.1.0/src/idun/gbm/split.py +404 -0
  37. idun-0.1.0/src/idun/gbm/train.py +539 -0
  38. idun-0.1.0/src/idun/gbm/tree.py +138 -0
  39. idun-0.1.0/src/idun/metal/__init__.py +4 -0
  40. idun-0.1.0/src/idun/metal/runtime.py +470 -0
  41. idun-0.1.0/src/idun/models.py +28 -0
  42. idun-0.1.0/src/idun/nn/__init__.py +5 -0
  43. idun-0.1.0/src/idun/nn/estimator.py +206 -0
  44. idun-0.1.0/src/idun/nn/inputs.py +199 -0
  45. idun-0.1.0/src/idun/nn/kernels/metal/common.metal +175 -0
  46. idun-0.1.0/src/idun/nn/kernels/metal/rmlp.metal +489 -0
  47. idun-0.1.0/src/idun/nn/kernels/metal/tabm.metal +389 -0
  48. idun-0.1.0/src/idun/nn/metal.py +30 -0
  49. idun-0.1.0/src/idun/nn/table.py +89 -0
  50. idun-0.1.0/src/idun/nn/training.py +34 -0
  51. idun-0.1.0/src/idun/py.typed +0 -0
  52. idun-0.1.0/src/idun/realmlp/__init__.py +19 -0
  53. idun-0.1.0/src/idun/realmlp/estimator.py +91 -0
  54. idun-0.1.0/src/idun/realmlp/metal.py +554 -0
  55. idun-0.1.0/src/idun/realmlp/params.py +86 -0
  56. idun-0.1.0/src/idun/realmlp/reference.py +364 -0
  57. idun-0.1.0/src/idun/realmlp/train.py +537 -0
  58. idun-0.1.0/src/idun/rng.py +168 -0
  59. idun-0.1.0/src/idun/tabm/__init__.py +11 -0
  60. idun-0.1.0/src/idun/tabm/estimator.py +72 -0
  61. idun-0.1.0/src/idun/tabm/metal.py +425 -0
  62. idun-0.1.0/src/idun/tabm/params.py +79 -0
  63. idun-0.1.0/src/idun/tabm/reference.py +248 -0
  64. idun-0.1.0/src/idun/tabm/train.py +329 -0
@@ -0,0 +1,39 @@
1
+ # Native layer of Idun. It builds the Metal runtime; a CUDA target with the same C ABI conventions would join it
2
+ # (enable_language(CUDA) behind an option), which is why this is CMake and not a one-line clang call.
3
+ cmake_minimum_required(VERSION 3.28)
4
+ # Before project(), or it does not apply; FORCE so that an existing build tree takes it too (a build without it targets
5
+ # the SDK's macOS, 26, and cannot load on 15).
6
+ set(CMAKE_OSX_DEPLOYMENT_TARGET "15.0" CACHE STRING "MSL 3.2 needs macOS 15" FORCE)
7
+ project(idun_native LANGUAGES C CXX OBJCXX)
8
+
9
+ if(NOT APPLE)
10
+ message(FATAL_ERROR "The Metal runtime builds on macOS only; there is no CUDA backend yet.")
11
+ endif()
12
+
13
+ set(CMAKE_CXX_STANDARD 20)
14
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
15
+ set(CMAKE_OBJCXX_STANDARD 20)
16
+ set(CMAKE_OBJCXX_STANDARD_REQUIRED ON)
17
+ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
18
+
19
+ option(IDUN_COVERAGE "Instrument native code for llvm-cov (make coverage-native)" OFF)
20
+ set(IDUN_NATIVE_OUT "${CMAKE_SOURCE_DIR}/src/idun/_native" CACHE PATH "Where libidun_metal.dylib is written")
21
+ if(SKBUILD) # a wheel build (scikit-build-core): the build tree, then installed into the wheel, never the source tree
22
+ set(IDUN_NATIVE_OUT "${CMAKE_BINARY_DIR}/lib")
23
+ endif()
24
+
25
+ add_library(idun_metal SHARED native/metal/idun_metal.mm)
26
+ target_include_directories(idun_metal PUBLIC native/include)
27
+ target_compile_options(idun_metal PRIVATE -fobjc-arc -fvisibility=hidden -Wall -Wextra -Wpedantic -Wshadow
28
+ -Wconversion -Werror)
29
+ target_link_libraries(idun_metal PRIVATE "-framework Metal" "-framework Foundation")
30
+ set_target_properties(idun_metal PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${IDUN_NATIVE_OUT}")
31
+
32
+ if(IDUN_COVERAGE)
33
+ target_compile_options(idun_metal PRIVATE -O0 -fprofile-instr-generate -fcoverage-mapping)
34
+ target_link_options(idun_metal PRIVATE -fprofile-instr-generate)
35
+ endif()
36
+
37
+ if(SKBUILD)
38
+ install(TARGETS idun_metal LIBRARY DESTINATION idun/_native)
39
+ endif()
@@ -0,0 +1,27 @@
1
+ {
2
+ "version": 6,
3
+ "configurePresets": [
4
+ {
5
+ "name": "release",
6
+ "displayName": "Release: optimized, written into src/idun/_native",
7
+ "generator": "Ninja",
8
+ "binaryDir": "${sourceDir}/build/release",
9
+ "cacheVariables": { "CMAKE_BUILD_TYPE": "Release" }
10
+ },
11
+ {
12
+ "name": "coverage",
13
+ "displayName": "Coverage: llvm-cov instrumented, written into build/coverage",
14
+ "generator": "Ninja",
15
+ "binaryDir": "${sourceDir}/build/coverage",
16
+ "cacheVariables": {
17
+ "CMAKE_BUILD_TYPE": "Debug",
18
+ "IDUN_COVERAGE": "ON",
19
+ "IDUN_NATIVE_OUT": "${sourceDir}/build/coverage/lib"
20
+ }
21
+ }
22
+ ],
23
+ "buildPresets": [
24
+ { "name": "release", "configurePreset": "release" },
25
+ { "name": "coverage", "configurePreset": "coverage" }
26
+ ]
27
+ }
idun-0.1.0/LICENSE ADDED
@@ -0,0 +1,202 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
idun-0.1.0/NOTICE ADDED
@@ -0,0 +1,39 @@
1
+ idun
2
+ Copyright 2026 Anton Shaniuk
3
+
4
+ Licensed under the Apache License, Version 2.0 (LICENSE).
5
+
6
+ The Metal GEMM kernel (idun/nn/kernels/metal/common.metal) is adapted from MLX's Steel GEMM
7
+ (https://github.com/ml-explore/mlx): its tile loader's thread layout and its fragment lane coordinates. MLX's copyright
8
+ and permission notice:
9
+
10
+ MIT License
11
+
12
+ Copyright © 2023 Apple Inc.
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+
32
+ idun_tabm implements TabM: Yury Gorishniy, Akim Kotelnikov and Artem Babenko, "TabM: Advancing Tabular Deep Learning
33
+ with Parameter-Efficient Ensembling", ICLR 2025, arXiv:2410.24210.
34
+
35
+ idun_realmlp implements RealMLP-TD: David Holzmüller, Léo Grinsztajn and Ingo Steinwart, "Better by Default: Strong
36
+ Pre-Tuned MLPs and Boosted Trees on Tabular Data", NeurIPS 2024, arXiv:2407.04491.
37
+
38
+ idun_gbm follows LightGBM's model: Guolin Ke et al., "LightGBM: A Highly Efficient Gradient Boosting Decision Tree",
39
+ NeurIPS 2017.
idun-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: idun
3
+ Version: 0.1.0
4
+ Summary: Tabular learners for the Apple silicon GPU (Metal): idun_gbm, idun_tabm and idun_realmlp, with CPU reference backends.
5
+ Keywords: gradient boosting,tabular,deep learning,TabM,RealMLP,Metal,Apple silicon,GPU
6
+ Author: Anton Shaniuk
7
+ License-Expression: Apache-2.0
8
+ License-File: LICENSE
9
+ License-File: NOTICE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Operating System :: MacOS
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: <3.15,>=3.12
21
+ Requires-Dist: numpy<3,>=2.5
22
+ Requires-Dist: numba<0.69,>=0.68
23
+ Description-Content-Type: text/markdown
24
+
25
+ # idun
26
+
27
+ Tabular learning on the Apple silicon GPU. idun trains three learners on Metal, each with a CPU reference backend:
28
+
29
+ - **idun_gbm** (`idun.gbm`): histogram gradient boosting with LightGBM's model (depth-wise or leaf-wise trees,
30
+ quantized gradients, categorical splits, seed bags). Its CPU and Metal backends build the same model, bit for bit.
31
+ - **idun_tabm** (`idun.tabm`): TabM (Gorishniy et al., ICLR 2025), a parameter-efficient ensemble of MLPs.
32
+ - **idun_realmlp** (`idun.realmlp`): RealMLP-TD (Holzmüller et al., NeurIPS 2024).
33
+
34
+ Every fit is deterministic: the same data, parameters and seed give the same bits, run after run (the networks on the
35
+ same GPU). The estimators follow scikit-learn's conventions without depending on it.
36
+
37
+ idun is in alpha (0.1): the interfaces may still change.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ pip install idun # Apple silicon with macOS 15 or later: the Metal wheel; elsewhere the CPU-only wheel
43
+ pip install idun-numerai # the Numerai port
44
+ ```
45
+
46
+ Python 3.12–3.14; the only dependencies are NumPy and numba. Metal needs an Apple silicon Mac (M1 or newer) with
47
+ macOS 15 or later. On Linux and Intel Macs the same package installs without the Metal library and runs the CPU
48
+ backends; asking for Metal there raises `idun.errors.BackendUnavailableError` rather than falling back.
49
+
50
+ ## Quick start
51
+
52
+ ```python
53
+ import idun
54
+ from idun.gbm import GBMRegressor
55
+ from idun.realmlp import RealMLPRegressor
56
+ from idun.tabm import TabMClassifier
57
+
58
+ gbm = GBMRegressor(num_trees=300, learning_rate=0.05).fit(X_train, y_train)
59
+ pred = gbm.predict(X_test)
60
+ cpu = GBMRegressor(num_trees=300, learning_rate=0.05, backend="cpu").fit(X_train, y_train) # the same trees
61
+
62
+ clf = TabMClassifier(categorical=["sector"]).fit(X_train, labels) # any labels, two classes or more
63
+ proba = clf.predict_proba(X_test)
64
+
65
+ mlp = RealMLPRegressor(n_seeds=4).fit(X_train, y_train) # a bag of four seeds; predicts their mean
66
+
67
+ gbm.save("gbm.idun")
68
+ same = idun.load("gbm.idun")
69
+ ```
70
+
71
+ `X` is a 2-D NumPy array, a pandas DataFrame or an Arrow table; missing values are allowed. The backend is `"metal"`
72
+ by default; pass `backend="cpu"` (idun_gbm) or `backend="reference"` (the networks' float64 reference) to run on the
73
+ CPU. Nothing switches backends behind your back.
74
+
75
+ Below the estimators: `idun.Dataset` bins a table once for reuse; the functional layer (`idun.gbm.train`,
76
+ `idun.tabm.train_tabm`, `idun.realmlp.train_realmlp`, seed bags through `train_seeds` and `predict_mean`) trains on
77
+ binned data or on `idun.data.PackedDataset`, a memory-mapped, date-sorted panel for data larger than memory, which
78
+ Metal reads without a copy. The docstrings document every public name.
79
+
80
+ ## How it compares
81
+
82
+ On five OpenML tasks on an Apple M1 (8 GB): idun_gbm's RMSE is within 3 % of the median of LightGBM, XGBoost and
83
+ scikit-learn's HistGradientBoosting at the same nominal settings; idun_tabm and idun_realmlp are within 2 % of their
84
+ reference implementations (the `tabm` package and pytabkit on Torch's MPS device) on every task and better on most, and
85
+ idun_tabm fits in 0.45 of the reference's time.
86
+
87
+ ## Licence
88
+
89
+ Apache-2.0. The NOTICE file lists the work idun builds on, including MLX's Steel GEMM (MIT), whose structure the
90
+ networks' GEMM kernel adapts.
idun-0.1.0/README.md ADDED
@@ -0,0 +1,66 @@
1
+ # idun
2
+
3
+ Tabular learning on the Apple silicon GPU. idun trains three learners on Metal, each with a CPU reference backend:
4
+
5
+ - **idun_gbm** (`idun.gbm`): histogram gradient boosting with LightGBM's model (depth-wise or leaf-wise trees,
6
+ quantized gradients, categorical splits, seed bags). Its CPU and Metal backends build the same model, bit for bit.
7
+ - **idun_tabm** (`idun.tabm`): TabM (Gorishniy et al., ICLR 2025), a parameter-efficient ensemble of MLPs.
8
+ - **idun_realmlp** (`idun.realmlp`): RealMLP-TD (Holzmüller et al., NeurIPS 2024).
9
+
10
+ Every fit is deterministic: the same data, parameters and seed give the same bits, run after run (the networks on the
11
+ same GPU). The estimators follow scikit-learn's conventions without depending on it.
12
+
13
+ idun is in alpha (0.1): the interfaces may still change.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ pip install idun # Apple silicon with macOS 15 or later: the Metal wheel; elsewhere the CPU-only wheel
19
+ pip install idun-numerai # the Numerai port
20
+ ```
21
+
22
+ Python 3.12–3.14; the only dependencies are NumPy and numba. Metal needs an Apple silicon Mac (M1 or newer) with
23
+ macOS 15 or later. On Linux and Intel Macs the same package installs without the Metal library and runs the CPU
24
+ backends; asking for Metal there raises `idun.errors.BackendUnavailableError` rather than falling back.
25
+
26
+ ## Quick start
27
+
28
+ ```python
29
+ import idun
30
+ from idun.gbm import GBMRegressor
31
+ from idun.realmlp import RealMLPRegressor
32
+ from idun.tabm import TabMClassifier
33
+
34
+ gbm = GBMRegressor(num_trees=300, learning_rate=0.05).fit(X_train, y_train)
35
+ pred = gbm.predict(X_test)
36
+ cpu = GBMRegressor(num_trees=300, learning_rate=0.05, backend="cpu").fit(X_train, y_train) # the same trees
37
+
38
+ clf = TabMClassifier(categorical=["sector"]).fit(X_train, labels) # any labels, two classes or more
39
+ proba = clf.predict_proba(X_test)
40
+
41
+ mlp = RealMLPRegressor(n_seeds=4).fit(X_train, y_train) # a bag of four seeds; predicts their mean
42
+
43
+ gbm.save("gbm.idun")
44
+ same = idun.load("gbm.idun")
45
+ ```
46
+
47
+ `X` is a 2-D NumPy array, a pandas DataFrame or an Arrow table; missing values are allowed. The backend is `"metal"`
48
+ by default; pass `backend="cpu"` (idun_gbm) or `backend="reference"` (the networks' float64 reference) to run on the
49
+ CPU. Nothing switches backends behind your back.
50
+
51
+ Below the estimators: `idun.Dataset` bins a table once for reuse; the functional layer (`idun.gbm.train`,
52
+ `idun.tabm.train_tabm`, `idun.realmlp.train_realmlp`, seed bags through `train_seeds` and `predict_mean`) trains on
53
+ binned data or on `idun.data.PackedDataset`, a memory-mapped, date-sorted panel for data larger than memory, which
54
+ Metal reads without a copy. The docstrings document every public name.
55
+
56
+ ## How it compares
57
+
58
+ On five OpenML tasks on an Apple M1 (8 GB): idun_gbm's RMSE is within 3 % of the median of LightGBM, XGBoost and
59
+ scikit-learn's HistGradientBoosting at the same nominal settings; idun_tabm and idun_realmlp are within 2 % of their
60
+ reference implementations (the `tabm` package and pytabkit on Torch's MPS device) on every task and better on most, and
61
+ idun_tabm fits in 0.45 of the reference's time.
62
+
63
+ ## Licence
64
+
65
+ Apache-2.0. The NOTICE file lists the work idun builds on, including MLX's Steel GEMM (MIT), whose structure the
66
+ networks' GEMM kernel adapts.
@@ -0,0 +1,111 @@
1
+ /*
2
+ * idun_metal.h - C ABI of the Idun Metal runtime (libidun_metal.dylib).
3
+ *
4
+ * Python binds this header through ctypes (src/idun/metal/runtime.py). Conventions, which a CUDA backend would follow
5
+ * too (docs/architecture/backend-interface.md):
6
+ * - every function is extern "C", takes and returns only C types, and never lets an exception or Objective-C
7
+ * exception cross the boundary;
8
+ * - fallible functions return IDUN_OK (0) on success, or a negative IDUN_ERR_* code with a NUL-terminated message
9
+ * written to (err, err_len); err may be NULL when err_len is 0; functions returning a handle return NULL on
10
+ * failure and write the message the same way;
11
+ * - the caller owns the memory it passes in; the library owns the handles it returns until the matching
12
+ * _destroy/_free; kernels belong to their context;
13
+ * - IDUN_ABI_VERSION changes on every incompatible change, and the binding refuses to load a mismatched library.
14
+ */
15
+ #ifndef IDUN_METAL_H
16
+ #define IDUN_METAL_H
17
+
18
+ #include <stddef.h>
19
+ #include <stdint.h>
20
+
21
+ #ifdef __cplusplus
22
+ extern "C" {
23
+ #endif
24
+
25
+ #define IDUN_ABI_VERSION 6
26
+
27
+ #define IDUN_OK 0
28
+ #define IDUN_ERR_NO_DEVICE (-1)
29
+ #define IDUN_ERR_COMPILE (-2)
30
+ #define IDUN_ERR_ARGUMENT (-3)
31
+ #define IDUN_ERR_STATE (-4) /* a call out of order: dispatch without a batch, a kernel before a library, ... */
32
+ #define IDUN_ERR_GPU (-5) /* a command buffer failed on the device */
33
+
34
+ #define IDUN_NAME_LEN 128
35
+ #define IDUN_MAX_BUFFERS 30 /* buffer indices 0..29; the params block goes to index n_buffers */
36
+ #define IDUN_MAX_PARAMS 4096 /* setBytes limit */
37
+
38
+ typedef struct idun_device_info {
39
+ char name[IDUN_NAME_LEN];
40
+ uint64_t max_threadgroup_memory_bytes;
41
+ uint64_t recommended_working_set_bytes;
42
+ uint64_t max_buffer_bytes;
43
+ uint32_t max_threads_per_threadgroup;
44
+ uint32_t page_size_bytes;
45
+ uint32_t has_unified_memory;
46
+ uint32_t supports_apple7; /* M1 family and newer: what the idun_gbm Metal backend needs */
47
+ uint32_t supports_apple9; /* M4 family: SIMD width 32, 32 KiB threadgroup memory */
48
+ uint32_t supports_metal4;
49
+ } idun_device_info;
50
+
51
+ typedef struct idun_context idun_context; /* device, queue, library, kernels, the open command batch */
52
+ typedef struct idun_kernel idun_kernel; /* a compute pipeline, owned by its context */
53
+ typedef struct idun_buffer idun_buffer; /* a shared-storage MTLBuffer */
54
+
55
+ /* IDUN_ABI_VERSION of the compiled library. */
56
+ int32_t idun_abi_version(void);
57
+
58
+ /* The source text prepended to every kernel library before compilation (determinism.md: FP contraction off). */
59
+ const char *idun_source_prelude(void);
60
+
61
+ /* Describe the system default Metal device. */
62
+ int32_t idun_probe(idun_device_info *out, char *err, size_t err_len);
63
+
64
+ /* Compile MSL `source` with Idun's fixed compile options and prelude; on failure the compiler log goes to err. */
65
+ int32_t idun_compile_check(const char *source, char *err, size_t err_len);
66
+
67
+ /* A context on the system default device: one command queue, at most one library, at most one open batch. */
68
+ idun_context *idun_context_create(char *err, size_t err_len);
69
+ /* Destroy a context and its kernels (buffers are freed separately). Commits nothing: an open batch is dropped;
70
+ * committed batches are waited for (their errors are not reported). */
71
+ void idun_context_destroy(idun_context *ctx);
72
+
73
+ /* Compile `source` (with the prelude and fixed options) as the context's library; replaces kernels of a previous one.
74
+ */
75
+ int32_t idun_library_load(idun_context *ctx, const char *source, char *err, size_t err_len);
76
+ /* The compute pipeline of kernel function `name` of the loaded library. */
77
+ idun_kernel *idun_kernel_get(idun_context *ctx, const char *name, char *err, size_t err_len);
78
+ /* Largest threadgroup the pipeline accepts, and its SIMD width. */
79
+ uint32_t idun_kernel_max_threads(const idun_kernel *kernel);
80
+ uint32_t idun_kernel_simd_width(const idun_kernel *kernel);
81
+
82
+ /* A new zero-filled shared buffer of `bytes` (> 0); its CPU address goes to *contents. */
83
+ idun_buffer *idun_buffer_alloc(idun_context *ctx, size_t bytes, void **contents, char *err, size_t err_len);
84
+ /* Wrap caller memory without copying: `page_aligned` and `bytes` must be multiples of the page size. The memory must
85
+ * stay valid and mapped until idun_buffer_free; the GPU may read it (and write it, if the mapping is writable). */
86
+ idun_buffer *idun_buffer_wrap(idun_context *ctx, void *page_aligned, size_t bytes, char *err, size_t err_len);
87
+ void idun_buffer_free(idun_buffer *buffer);
88
+
89
+ /* Open a command batch: one command buffer with one serial compute encoder. */
90
+ int32_t idun_batch_begin(idun_context *ctx, char *err, size_t err_len);
91
+ /* Encode one dispatch into the open batch: buffers at indices 0..n_buffers-1, `params` (if any) at index n_buffers,
92
+ * `threadgroup_bytes` (a multiple of 16; 0 for none) of dynamic threadgroup memory at threadgroup index 0, `groups`
93
+ * threadgroups of `threads` threads. Dispatches of one batch run in order. */
94
+ int32_t idun_dispatch(idun_context *ctx, const idun_kernel *kernel, idun_buffer *const *buffers, uint32_t n_buffers,
95
+ const void *params, size_t params_bytes, uint32_t threadgroup_bytes, const uint32_t groups[3],
96
+ const uint32_t threads[3], char *err, size_t err_len);
97
+ /* Commit the open batch without waiting (v5). Batches run in the order they are committed, each after the one before
98
+ * it finished, so the host can encode the next batch while the GPU runs this one. */
99
+ int32_t idun_batch_commit(idun_context *ctx, char *err, size_t err_len);
100
+ /* Wait, oldest first, until at most `keep` committed batches are left unwaited (v5); report the GPU time of those
101
+ * waited for (sum of GPUEndTime - GPUStartTime). Returns IDUN_ERR_GPU with the first failure's message if any failed.
102
+ */
103
+ int32_t idun_batch_wait(idun_context *ctx, uint32_t keep, double *gpu_seconds, char *err, size_t err_len);
104
+ /* Commit the open batch and wait for it and every batch committed before it; report their GPU time. */
105
+ int32_t idun_batch_commit_wait(idun_context *ctx, double *gpu_seconds, char *err, size_t err_len);
106
+
107
+ #ifdef __cplusplus
108
+ }
109
+ #endif
110
+
111
+ #endif /* IDUN_METAL_H */