raglu 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.
- raglu-0.1.0/LICENSE +21 -0
- raglu-0.1.0/PKG-INFO +192 -0
- raglu-0.1.0/README.md +159 -0
- raglu-0.1.0/pyproject.toml +61 -0
- raglu-0.1.0/raglu/__init__.py +31 -0
- raglu-0.1.0/raglu/core.py +116 -0
- raglu-0.1.0/raglu/py.typed +0 -0
- raglu-0.1.0/raglu/torch_module.py +121 -0
- raglu-0.1.0/raglu.egg-info/PKG-INFO +192 -0
- raglu-0.1.0/raglu.egg-info/SOURCES.txt +13 -0
- raglu-0.1.0/raglu.egg-info/dependency_links.txt +1 -0
- raglu-0.1.0/raglu.egg-info/requires.txt +12 -0
- raglu-0.1.0/raglu.egg-info/top_level.txt +1 -0
- raglu-0.1.0/setup.cfg +4 -0
- raglu-0.1.0/tests/test_raglu.py +289 -0
raglu-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ömer Faruk Solmaz
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
raglu-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: raglu
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pure Rational GLU (RaGLU) and RaLU activations for PyTorch, Triton CUDA and Apple MLX.
|
|
5
|
+
Author: Ömer Faruk Solmaz
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: activation,glu,ralu,rational,pytorch,triton,mlx,deep-learning
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: torch>=2.0.0
|
|
24
|
+
Provides-Extra: triton
|
|
25
|
+
Requires-Dist: triton>=2.0.0; extra == "triton"
|
|
26
|
+
Provides-Extra: mlx
|
|
27
|
+
Requires-Dist: mlx>=0.1.0; extra == "mlx"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# RaGLU
|
|
35
|
+
|
|
36
|
+
**Pure Rational GLU (RaGLU)** ve **RaLU** aktivasyon fonksiyonları için platform
|
|
37
|
+
bağımsız PyTorch kütüphanesi. NVIDIA CUDA'da isteğe bağlı **Triton** çekirdekleri,
|
|
38
|
+
Apple Silicon'da ise yerel **MLX** desteği sunar.
|
|
39
|
+
|
|
40
|
+
Paket iki `nn.Module` sınıfı sunar:
|
|
41
|
+
|
|
42
|
+
| Sınıf | Görevi |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `RaGLU()` | Kapılı (GLU) katman: `Linear` çıktısını gate/val olarak ikiye böler, `f(g) * v` uygular. |
|
|
45
|
+
| `RaLU()` | Kapısız, element-wise aktivasyon: `f(x)` uygular, şekli değiştirmez. |
|
|
46
|
+
|
|
47
|
+
## Fonksiyonlar
|
|
48
|
+
|
|
49
|
+
Kapılı (gated) varyant:
|
|
50
|
+
|
|
51
|
+
$$
|
|
52
|
+
\operatorname{RaGLU}(g, v) = \frac{g^3 + g}{g^2 + 3} \cdot v
|
|
53
|
+
$$
|
|
54
|
+
|
|
55
|
+
Kapısız varyant:
|
|
56
|
+
|
|
57
|
+
$$
|
|
58
|
+
\operatorname{RaLU}(x) = \frac{x^3 + x}{x^2 + 3}
|
|
59
|
+
$$
|
|
60
|
+
|
|
61
|
+
Türev (her iki varyantın çekirdeği):
|
|
62
|
+
|
|
63
|
+
$$
|
|
64
|
+
\frac{d}{dx}\left(\frac{x^3 + x}{x^2 + 3}\right)
|
|
65
|
+
= \frac{x^4 + 8x^2 + 3}{(x^2 + 3)^2}
|
|
66
|
+
$$
|
|
67
|
+
|
|
68
|
+
Fonksiyon tek (odd) bir fonksiyondur: `f(-x) = -f(x)`. Payda her zaman
|
|
69
|
+
`>= 3` olduğundan sayısal olarak kararlıdır.
|
|
70
|
+
|
|
71
|
+
## Kurulum
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install raglu
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
İsteğe bağlı hızlandırıcılar:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install "raglu[triton]" # NVIDIA CUDA için Triton çekirdekleri
|
|
81
|
+
pip install "raglu[mlx]" # Apple Silicon için MLX
|
|
82
|
+
pip install "raglu[dev]" # test + derleme araçları
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Kullanım
|
|
86
|
+
|
|
87
|
+
### Fonksiyonel PyTorch API
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
import torch
|
|
91
|
+
from raglu import fused_pure_rational_glu, fused_pure_rational
|
|
92
|
+
|
|
93
|
+
gate = torch.randn(32, 128)
|
|
94
|
+
val = torch.randn(32, 128)
|
|
95
|
+
|
|
96
|
+
y = fused_pure_rational_glu(gate, val) # (32, 128)
|
|
97
|
+
z = fused_pure_rational(gate) # (32, 128)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`fused_pure_rational_glu`, CUDA + Triton mevcutsa füzyonlu çekirdeği kullanır.
|
|
101
|
+
Aksi halde otomatik olarak CPU/MPS uyumlu PyTorch fallback'ine döner.
|
|
102
|
+
Her iki yol da autograd desteklidir.
|
|
103
|
+
|
|
104
|
+
### Katmanlar
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
import torch
|
|
108
|
+
from raglu import RaGLU, RaLU
|
|
109
|
+
|
|
110
|
+
# Girdiyi 2 * out_features boyutuna genişletip gate/val olarak böler.
|
|
111
|
+
layer = RaGLU(in_features=768, out_features=768)
|
|
112
|
+
x = torch.randn(8, 128, 768)
|
|
113
|
+
y = layer(x) # (8, 128, 768)
|
|
114
|
+
|
|
115
|
+
# Kapısız aktivasyon
|
|
116
|
+
act = RaLU()
|
|
117
|
+
z = act(x) # (8, 128, 768)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Hazır `gate` ve `val` modülleri de kullanılabilir:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from torch import nn
|
|
124
|
+
from raglu import RaGLU
|
|
125
|
+
|
|
126
|
+
layer = RaGLU(
|
|
127
|
+
gate=nn.Linear(768, 1024),
|
|
128
|
+
val=nn.Linear(768, 1024),
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Apple MLX
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import mlx.core as mx
|
|
136
|
+
from raglu import mlx_pure_rational_glu, mlx_pure_rational
|
|
137
|
+
|
|
138
|
+
gate = mx.random.normal((32, 128))
|
|
139
|
+
val = mx.random.normal((32, 128))
|
|
140
|
+
|
|
141
|
+
y = mlx_pure_rational_glu(gate, val)
|
|
142
|
+
z = mlx_pure_rational(gate)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
MLX kurulu değilse bu semboller dışa aktarılmaz; `raglu.HAS_MLX` ile kontrol
|
|
146
|
+
edebilirsiniz.
|
|
147
|
+
|
|
148
|
+
## API
|
|
149
|
+
|
|
150
|
+
| Sembol | Açıklama |
|
|
151
|
+
| --- | --- |
|
|
152
|
+
| `raglu.fused_pure_rational_glu(gate, val)` | Kapılı Pure Rational GLU (Triton/CUDA veya PyTorch fallback) |
|
|
153
|
+
| `raglu.fused_pure_rational(x)` | Kapısız RaLU aktivasyonu |
|
|
154
|
+
| `raglu.RaGLU` | Doğrusal katman + Pure Rational GLU `nn.Module`'ü |
|
|
155
|
+
| `raglu.RaLU` | Element-wise RaLU `nn.Module`'ü |
|
|
156
|
+
| `raglu.mlx_pure_rational_glu` | MLX kapılı varyant (MLX varsa) |
|
|
157
|
+
| `raglu.mlx_pure_rational` | MLX kapısız varyant (MLX varsa) |
|
|
158
|
+
| `raglu.HAS_TRITON` | Triton çekirdeklerinin kullanılabilirliği |
|
|
159
|
+
| `raglu.HAS_MLX` | MLX'in kullanılabilirliği |
|
|
160
|
+
|
|
161
|
+
### Not: CUDA clamp
|
|
162
|
+
|
|
163
|
+
Triton çekirdekleri sayısal kararlılık için kapı değerini `[-50, 50]` aralığına
|
|
164
|
+
kırpar. Bu aralığın dışındaki değerlerde Triton ve fallback çıktıları
|
|
165
|
+
farklılaşabilir; pratik aktivasyon girdilerinde fark yoktur.
|
|
166
|
+
|
|
167
|
+
## Geliştirme
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
git clone <repo-url>
|
|
171
|
+
cd RaGLU
|
|
172
|
+
python -m venv .venv
|
|
173
|
+
source .venv/bin/activate
|
|
174
|
+
pip install -e ".[dev]"
|
|
175
|
+
pytest -v
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Triton testleri yalnızca CUDA + Triton mevcut olduğunda, MLX testleri ise
|
|
179
|
+
yalnızca MLX kurulu olduğunda çalışır; diğer ortamlarda otomatik atlanır.
|
|
180
|
+
|
|
181
|
+
### Paket derleme
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
python -m build
|
|
185
|
+
python -m twine check dist/*
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Lisans
|
|
189
|
+
|
|
190
|
+
MIT — bkz. [LICENSE](LICENSE).
|
|
191
|
+
|
|
192
|
+
Copyright (c) 2026 Ömer Faruk Solmaz
|
raglu-0.1.0/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# RaGLU
|
|
2
|
+
|
|
3
|
+
**Pure Rational GLU (RaGLU)** ve **RaLU** aktivasyon fonksiyonları için platform
|
|
4
|
+
bağımsız PyTorch kütüphanesi. NVIDIA CUDA'da isteğe bağlı **Triton** çekirdekleri,
|
|
5
|
+
Apple Silicon'da ise yerel **MLX** desteği sunar.
|
|
6
|
+
|
|
7
|
+
Paket iki `nn.Module` sınıfı sunar:
|
|
8
|
+
|
|
9
|
+
| Sınıf | Görevi |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| `RaGLU()` | Kapılı (GLU) katman: `Linear` çıktısını gate/val olarak ikiye böler, `f(g) * v` uygular. |
|
|
12
|
+
| `RaLU()` | Kapısız, element-wise aktivasyon: `f(x)` uygular, şekli değiştirmez. |
|
|
13
|
+
|
|
14
|
+
## Fonksiyonlar
|
|
15
|
+
|
|
16
|
+
Kapılı (gated) varyant:
|
|
17
|
+
|
|
18
|
+
$$
|
|
19
|
+
\operatorname{RaGLU}(g, v) = \frac{g^3 + g}{g^2 + 3} \cdot v
|
|
20
|
+
$$
|
|
21
|
+
|
|
22
|
+
Kapısız varyant:
|
|
23
|
+
|
|
24
|
+
$$
|
|
25
|
+
\operatorname{RaLU}(x) = \frac{x^3 + x}{x^2 + 3}
|
|
26
|
+
$$
|
|
27
|
+
|
|
28
|
+
Türev (her iki varyantın çekirdeği):
|
|
29
|
+
|
|
30
|
+
$$
|
|
31
|
+
\frac{d}{dx}\left(\frac{x^3 + x}{x^2 + 3}\right)
|
|
32
|
+
= \frac{x^4 + 8x^2 + 3}{(x^2 + 3)^2}
|
|
33
|
+
$$
|
|
34
|
+
|
|
35
|
+
Fonksiyon tek (odd) bir fonksiyondur: `f(-x) = -f(x)`. Payda her zaman
|
|
36
|
+
`>= 3` olduğundan sayısal olarak kararlıdır.
|
|
37
|
+
|
|
38
|
+
## Kurulum
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install raglu
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
İsteğe bağlı hızlandırıcılar:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
pip install "raglu[triton]" # NVIDIA CUDA için Triton çekirdekleri
|
|
48
|
+
pip install "raglu[mlx]" # Apple Silicon için MLX
|
|
49
|
+
pip install "raglu[dev]" # test + derleme araçları
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Kullanım
|
|
53
|
+
|
|
54
|
+
### Fonksiyonel PyTorch API
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
import torch
|
|
58
|
+
from raglu import fused_pure_rational_glu, fused_pure_rational
|
|
59
|
+
|
|
60
|
+
gate = torch.randn(32, 128)
|
|
61
|
+
val = torch.randn(32, 128)
|
|
62
|
+
|
|
63
|
+
y = fused_pure_rational_glu(gate, val) # (32, 128)
|
|
64
|
+
z = fused_pure_rational(gate) # (32, 128)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
`fused_pure_rational_glu`, CUDA + Triton mevcutsa füzyonlu çekirdeği kullanır.
|
|
68
|
+
Aksi halde otomatik olarak CPU/MPS uyumlu PyTorch fallback'ine döner.
|
|
69
|
+
Her iki yol da autograd desteklidir.
|
|
70
|
+
|
|
71
|
+
### Katmanlar
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
import torch
|
|
75
|
+
from raglu import RaGLU, RaLU
|
|
76
|
+
|
|
77
|
+
# Girdiyi 2 * out_features boyutuna genişletip gate/val olarak böler.
|
|
78
|
+
layer = RaGLU(in_features=768, out_features=768)
|
|
79
|
+
x = torch.randn(8, 128, 768)
|
|
80
|
+
y = layer(x) # (8, 128, 768)
|
|
81
|
+
|
|
82
|
+
# Kapısız aktivasyon
|
|
83
|
+
act = RaLU()
|
|
84
|
+
z = act(x) # (8, 128, 768)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Hazır `gate` ve `val` modülleri de kullanılabilir:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from torch import nn
|
|
91
|
+
from raglu import RaGLU
|
|
92
|
+
|
|
93
|
+
layer = RaGLU(
|
|
94
|
+
gate=nn.Linear(768, 1024),
|
|
95
|
+
val=nn.Linear(768, 1024),
|
|
96
|
+
)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Apple MLX
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
import mlx.core as mx
|
|
103
|
+
from raglu import mlx_pure_rational_glu, mlx_pure_rational
|
|
104
|
+
|
|
105
|
+
gate = mx.random.normal((32, 128))
|
|
106
|
+
val = mx.random.normal((32, 128))
|
|
107
|
+
|
|
108
|
+
y = mlx_pure_rational_glu(gate, val)
|
|
109
|
+
z = mlx_pure_rational(gate)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
MLX kurulu değilse bu semboller dışa aktarılmaz; `raglu.HAS_MLX` ile kontrol
|
|
113
|
+
edebilirsiniz.
|
|
114
|
+
|
|
115
|
+
## API
|
|
116
|
+
|
|
117
|
+
| Sembol | Açıklama |
|
|
118
|
+
| --- | --- |
|
|
119
|
+
| `raglu.fused_pure_rational_glu(gate, val)` | Kapılı Pure Rational GLU (Triton/CUDA veya PyTorch fallback) |
|
|
120
|
+
| `raglu.fused_pure_rational(x)` | Kapısız RaLU aktivasyonu |
|
|
121
|
+
| `raglu.RaGLU` | Doğrusal katman + Pure Rational GLU `nn.Module`'ü |
|
|
122
|
+
| `raglu.RaLU` | Element-wise RaLU `nn.Module`'ü |
|
|
123
|
+
| `raglu.mlx_pure_rational_glu` | MLX kapılı varyant (MLX varsa) |
|
|
124
|
+
| `raglu.mlx_pure_rational` | MLX kapısız varyant (MLX varsa) |
|
|
125
|
+
| `raglu.HAS_TRITON` | Triton çekirdeklerinin kullanılabilirliği |
|
|
126
|
+
| `raglu.HAS_MLX` | MLX'in kullanılabilirliği |
|
|
127
|
+
|
|
128
|
+
### Not: CUDA clamp
|
|
129
|
+
|
|
130
|
+
Triton çekirdekleri sayısal kararlılık için kapı değerini `[-50, 50]` aralığına
|
|
131
|
+
kırpar. Bu aralığın dışındaki değerlerde Triton ve fallback çıktıları
|
|
132
|
+
farklılaşabilir; pratik aktivasyon girdilerinde fark yoktur.
|
|
133
|
+
|
|
134
|
+
## Geliştirme
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
git clone <repo-url>
|
|
138
|
+
cd RaGLU
|
|
139
|
+
python -m venv .venv
|
|
140
|
+
source .venv/bin/activate
|
|
141
|
+
pip install -e ".[dev]"
|
|
142
|
+
pytest -v
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Triton testleri yalnızca CUDA + Triton mevcut olduğunda, MLX testleri ise
|
|
146
|
+
yalnızca MLX kurulu olduğunda çalışır; diğer ortamlarda otomatik atlanır.
|
|
147
|
+
|
|
148
|
+
### Paket derleme
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
python -m build
|
|
152
|
+
python -m twine check dist/*
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Lisans
|
|
156
|
+
|
|
157
|
+
MIT — bkz. [LICENSE](LICENSE).
|
|
158
|
+
|
|
159
|
+
Copyright (c) 2026 Ömer Faruk Solmaz
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "raglu"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Pure Rational GLU (RaGLU) and RaLU activations for PyTorch, Triton CUDA and Apple MLX."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "Ömer Faruk Solmaz" },
|
|
15
|
+
]
|
|
16
|
+
keywords = [
|
|
17
|
+
"activation",
|
|
18
|
+
"glu",
|
|
19
|
+
"ralu",
|
|
20
|
+
"rational",
|
|
21
|
+
"pytorch",
|
|
22
|
+
"triton",
|
|
23
|
+
"mlx",
|
|
24
|
+
"deep-learning",
|
|
25
|
+
]
|
|
26
|
+
classifiers = [
|
|
27
|
+
"Development Status :: 4 - Beta",
|
|
28
|
+
"Intended Audience :: Developers",
|
|
29
|
+
"Intended Audience :: Science/Research",
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
32
|
+
"Programming Language :: Python :: 3.9",
|
|
33
|
+
"Programming Language :: Python :: 3.10",
|
|
34
|
+
"Programming Language :: Python :: 3.11",
|
|
35
|
+
"Programming Language :: Python :: 3.12",
|
|
36
|
+
"Programming Language :: Python :: 3.13",
|
|
37
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
38
|
+
"Typing :: Typed",
|
|
39
|
+
]
|
|
40
|
+
dependencies = [
|
|
41
|
+
"torch>=2.0.0",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.optional-dependencies]
|
|
45
|
+
triton = ["triton>=2.0.0"]
|
|
46
|
+
mlx = ["mlx>=0.1.0"]
|
|
47
|
+
dev = [
|
|
48
|
+
"pytest>=7.0.0",
|
|
49
|
+
"build>=1.0.0",
|
|
50
|
+
"twine>=4.0.0",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[tool.setuptools.packages.find]
|
|
54
|
+
include = ["raglu*"]
|
|
55
|
+
|
|
56
|
+
[tool.setuptools.package-data]
|
|
57
|
+
raglu = ["py.typed"]
|
|
58
|
+
|
|
59
|
+
[tool.pytest.ini_options]
|
|
60
|
+
testpaths = ["tests"]
|
|
61
|
+
addopts = "-ra"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""RaGLU: Pure Rational GLU ve RaLU aktivasyonları.
|
|
2
|
+
|
|
3
|
+
PyTorch (CPU/CUDA/MPS), isteğe bağlı Triton CUDA çekirdekleri ve Apple MLX
|
|
4
|
+
desteği sunar.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .core import (
|
|
8
|
+
HAS_MLX,
|
|
9
|
+
HAS_TRITON,
|
|
10
|
+
fused_pure_rational,
|
|
11
|
+
fused_pure_rational_glu,
|
|
12
|
+
)
|
|
13
|
+
from .torch_module import RaGLU, RaLU
|
|
14
|
+
|
|
15
|
+
if HAS_MLX:
|
|
16
|
+
from .core import mlx_pure_rational, mlx_pure_rational_glu
|
|
17
|
+
|
|
18
|
+
__version__ = "0.1.0"
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"fused_pure_rational_glu",
|
|
22
|
+
"fused_pure_rational",
|
|
23
|
+
"RaGLU",
|
|
24
|
+
"RaLU",
|
|
25
|
+
"HAS_TRITON",
|
|
26
|
+
"HAS_MLX",
|
|
27
|
+
"__version__",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
if HAS_MLX:
|
|
31
|
+
__all__ += ["mlx_pure_rational_glu", "mlx_pure_rational"]
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import torch
|
|
2
|
+
|
|
3
|
+
# Triton ve CUDA kontrolü
|
|
4
|
+
HAS_TRITON = False
|
|
5
|
+
if torch.cuda.is_available():
|
|
6
|
+
try:
|
|
7
|
+
import triton
|
|
8
|
+
import triton.language as tl
|
|
9
|
+
HAS_TRITON = True
|
|
10
|
+
except ImportError:
|
|
11
|
+
HAS_TRITON = False
|
|
12
|
+
|
|
13
|
+
# MLX kontrolü (Apple Silicon / Mac desteği için)
|
|
14
|
+
HAS_MLX = False
|
|
15
|
+
try:
|
|
16
|
+
import mlx.core as mx
|
|
17
|
+
import mlx.nn as mx_nn
|
|
18
|
+
HAS_MLX = True
|
|
19
|
+
except ImportError:
|
|
20
|
+
HAS_MLX = False
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# ==============================================================================
|
|
24
|
+
# 1. TRITON KERNELS (NVIDIA CUDA OPTİMİZE)
|
|
25
|
+
# ==============================================================================
|
|
26
|
+
if HAS_TRITON:
|
|
27
|
+
@triton.jit
|
|
28
|
+
def _pure_rational_glu_fwd_kernel(gate_ptr, val_ptr, out_ptr, n_elements, BLOCK_SIZE: tl.constexpr):
|
|
29
|
+
pid = tl.program_id(axis=0)
|
|
30
|
+
offsets = pid * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
|
|
31
|
+
mask = offsets < n_elements
|
|
32
|
+
|
|
33
|
+
g = tl.load(gate_ptr + offsets, mask=mask)
|
|
34
|
+
v = tl.load(val_ptr + offsets, mask=mask)
|
|
35
|
+
|
|
36
|
+
g = tl.clamp(g, -50.0, 50.0)
|
|
37
|
+
g_sq = g * g
|
|
38
|
+
fg = (g * g_sq + g) / (g_sq + 3.0)
|
|
39
|
+
tl.store(out_ptr + offsets, fg * v, mask=mask)
|
|
40
|
+
|
|
41
|
+
@triton.jit
|
|
42
|
+
def _pure_rational_glu_bwd_kernel(dy_ptr, gate_ptr, val_ptr, dg_ptr, dv_ptr, n_elements, BLOCK_SIZE: tl.constexpr):
|
|
43
|
+
pid = tl.program_id(axis=0)
|
|
44
|
+
offsets = pid * BLOCK_SIZE + tl.arange(0, BLOCK_SIZE)
|
|
45
|
+
mask = offsets < n_elements
|
|
46
|
+
|
|
47
|
+
dy = tl.load(dy_ptr + offsets, mask=mask)
|
|
48
|
+
g = tl.load(gate_ptr + offsets, mask=mask)
|
|
49
|
+
v = tl.load(val_ptr + offsets, mask=mask)
|
|
50
|
+
|
|
51
|
+
g = tl.clamp(g, -50.0, 50.0)
|
|
52
|
+
g_sq = g * g
|
|
53
|
+
denom = g_sq + 3.0
|
|
54
|
+
|
|
55
|
+
fg = (g * g_sq + g) / denom
|
|
56
|
+
dv = dy * fg
|
|
57
|
+
dfg = (g_sq * g_sq + 8.0 * g_sq + 3.0) / (denom * denom)
|
|
58
|
+
dg = dy * v * dfg
|
|
59
|
+
|
|
60
|
+
tl.store(dv_ptr + offsets, dv, mask=mask)
|
|
61
|
+
tl.store(dg_ptr + offsets, dg, mask=mask)
|
|
62
|
+
|
|
63
|
+
class FusedPureRationalGLUFunction(torch.autograd.Function):
|
|
64
|
+
@staticmethod
|
|
65
|
+
def forward(ctx, gate, val):
|
|
66
|
+
gate_c, val_c = gate.contiguous(), val.contiguous()
|
|
67
|
+
n_elements = gate_c.numel()
|
|
68
|
+
out = torch.empty_like(gate_c)
|
|
69
|
+
GRID = lambda meta: (triton.cdiv(n_elements, meta['BLOCK_SIZE']),)
|
|
70
|
+
_pure_rational_glu_fwd_kernel[GRID](gate_c, val_c, out, n_elements, BLOCK_SIZE=1024)
|
|
71
|
+
ctx.save_for_backward(gate_c, val_c)
|
|
72
|
+
return out
|
|
73
|
+
|
|
74
|
+
@staticmethod
|
|
75
|
+
def backward(ctx, dy):
|
|
76
|
+
gate, val = ctx.saved_tensors
|
|
77
|
+
dy_c = dy.contiguous()
|
|
78
|
+
n_elements = gate.numel()
|
|
79
|
+
dgate, dval = torch.empty_like(gate), torch.empty_like(val)
|
|
80
|
+
GRID = lambda meta: (triton.cdiv(n_elements, meta['BLOCK_SIZE']),)
|
|
81
|
+
_pure_rational_glu_bwd_kernel[GRID](dy_c, gate, val, dgate, dval, n_elements, BLOCK_SIZE=1024)
|
|
82
|
+
return dgate, dval
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# ==============================================================================
|
|
86
|
+
# 2. PYTORCH API (CUDA + MPS/Mac + CPU FALLBACK)
|
|
87
|
+
# ==============================================================================
|
|
88
|
+
def fused_pure_rational_glu(gate: torch.Tensor, val: torch.Tensor) -> torch.Tensor:
|
|
89
|
+
"""Pure Rational GLU Function: f(g) = (g^3 + g) / (g^2 + 3) * v"""
|
|
90
|
+
if HAS_TRITON and gate.is_cuda:
|
|
91
|
+
return FusedPureRationalGLUFunction.apply(gate, val)
|
|
92
|
+
else:
|
|
93
|
+
# PyTorch Native Fallback (MPS, CPU veya Triton bulunmayan ortamlar)
|
|
94
|
+
g_sq = gate * gate
|
|
95
|
+
fg = (gate * g_sq + gate) / (g_sq + 3.0)
|
|
96
|
+
return fg * val
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def fused_pure_rational(x: torch.Tensor) -> torch.Tensor:
|
|
100
|
+
"""RaLU (Non-GLU Pure Rational): f(x) = (x^3 + x) / (x^2 + 3)"""
|
|
101
|
+
x_sq = x * x
|
|
102
|
+
return (x * x_sq + x) / (x_sq + 3.0)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
# ==============================================================================
|
|
106
|
+
# 3. APPLE MLX NATIVE DESTEĞİ
|
|
107
|
+
# ==============================================================================
|
|
108
|
+
if HAS_MLX:
|
|
109
|
+
def mlx_pure_rational_glu(gate: mx.array, val: mx.array) -> mx.array:
|
|
110
|
+
g_sq = mx.square(gate)
|
|
111
|
+
fg = (gate * g_sq + gate) / (g_sq + 3.0)
|
|
112
|
+
return fg * val
|
|
113
|
+
|
|
114
|
+
def mlx_pure_rational(x: mx.array) -> mx.array:
|
|
115
|
+
x_sq = mx.square(x)
|
|
116
|
+
return (x * x_sq + x) / (x_sq + 3.0)
|
|
File without changes
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""PyTorch ``nn.Module`` katman sarmalayıcıları.
|
|
2
|
+
|
|
3
|
+
``RaGLU`` gated (kapılı) doğrusal katmanı, ``RaLU`` ise kapısız
|
|
4
|
+
element-wise aktivasyonu sağlar.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from torch import Tensor, nn
|
|
10
|
+
|
|
11
|
+
from .core import fused_pure_rational, fused_pure_rational_glu
|
|
12
|
+
|
|
13
|
+
__all__ = ["RaGLU", "RaLU"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class RaGLU(nn.Module):
|
|
17
|
+
"""Pure Rational GLU katmanı.
|
|
18
|
+
|
|
19
|
+
İki kullanım biçimi vardır:
|
|
20
|
+
|
|
21
|
+
1. Yerleşik doğrusal katman (önerilen)::
|
|
22
|
+
|
|
23
|
+
layer = RaGLU(in_features=768, out_features=768)
|
|
24
|
+
y = layer(x) # x: (..., 768) -> y: (..., 768)
|
|
25
|
+
|
|
26
|
+
Girdi, tek bir doğrusal katmanla ``2 * out_features`` boyutuna
|
|
27
|
+
genişletilir ve ikiye bölünür. İlk yarı kapı (``gate``), ikinci yarı
|
|
28
|
+
değer (``val``) olarak kullanılır.
|
|
29
|
+
|
|
30
|
+
2. Hazır ``gate`` ve ``val`` modülleri ile::
|
|
31
|
+
|
|
32
|
+
layer = RaGLU(gate=nn.Linear(768, 1024), val=nn.Linear(768, 1024))
|
|
33
|
+
y = layer(x)
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
in_features: Girdi özellik sayısı (yerleşik modda zorunludur).
|
|
37
|
+
out_features: Çıktı özellik sayısı. Varsayılan olarak ``in_features``.
|
|
38
|
+
bias: Yerleşik doğrusal katmanda bias kullanılıp kullanılmayacağı.
|
|
39
|
+
gate: Hazır kapı modülü. Verilirse ``val`` da verilmelidir.
|
|
40
|
+
val: Hazır değer modülü. Verilirse ``gate`` de verilmelidir.
|
|
41
|
+
|
|
42
|
+
Girdi ve çıktı şekilleri aynı son boyuta sahip olmalıdır: ``gate`` ve
|
|
43
|
+
``val`` çıktıları eşleşmezse hata verilir.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
in_features: int | None = None,
|
|
49
|
+
out_features: int | None = None,
|
|
50
|
+
bias: bool = True,
|
|
51
|
+
gate: nn.Module | None = None,
|
|
52
|
+
val: nn.Module | None = None,
|
|
53
|
+
) -> None:
|
|
54
|
+
super().__init__()
|
|
55
|
+
|
|
56
|
+
self.in_features: int | None = in_features
|
|
57
|
+
self.out_features: int | None = out_features
|
|
58
|
+
|
|
59
|
+
if gate is not None or val is not None:
|
|
60
|
+
if gate is None or val is None:
|
|
61
|
+
raise ValueError("'gate' ve 'val' birlikte verilmelidir.")
|
|
62
|
+
if in_features is not None or out_features is not None:
|
|
63
|
+
raise ValueError(
|
|
64
|
+
"Hazır 'gate'/'val' modülleriyle 'in_features'/'out_features' birlikte kullanılamaz."
|
|
65
|
+
)
|
|
66
|
+
self.linear = None
|
|
67
|
+
self.gate = gate
|
|
68
|
+
self.val = val
|
|
69
|
+
else:
|
|
70
|
+
if in_features is None:
|
|
71
|
+
raise ValueError("'in_features' veya hem 'gate' hem 'val' verilmelidir.")
|
|
72
|
+
if out_features is None:
|
|
73
|
+
out_features = in_features
|
|
74
|
+
self.in_features = in_features
|
|
75
|
+
self.out_features = out_features
|
|
76
|
+
|
|
77
|
+
# Tek matmul ile gate ve val üretimi (GLU standardı).
|
|
78
|
+
self.linear: nn.Linear | None = nn.Linear(
|
|
79
|
+
in_features, 2 * out_features, bias=bias
|
|
80
|
+
)
|
|
81
|
+
self.gate = None
|
|
82
|
+
self.val = None
|
|
83
|
+
|
|
84
|
+
def forward(self, x: Tensor) -> Tensor:
|
|
85
|
+
"""``x`` üzerinde Pure Rational GLU uygular."""
|
|
86
|
+
if self.linear is not None:
|
|
87
|
+
gate, val = self.linear(x).chunk(2, dim=-1)
|
|
88
|
+
else:
|
|
89
|
+
gate = self.gate(x)
|
|
90
|
+
val = self.val(x)
|
|
91
|
+
if gate.shape != val.shape:
|
|
92
|
+
raise ValueError(
|
|
93
|
+
f"'gate' ve 'val' çıktı şekilleri eşleşmiyor: "
|
|
94
|
+
f"{tuple(gate.shape)} != {tuple(val.shape)}"
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
return fused_pure_rational_glu(gate, val)
|
|
98
|
+
|
|
99
|
+
def extra_repr(self) -> str:
|
|
100
|
+
if self.linear is not None:
|
|
101
|
+
return (
|
|
102
|
+
f"in_features={self.in_features}, out_features={self.out_features}, "
|
|
103
|
+
f"bias={self.linear.bias is not None}"
|
|
104
|
+
)
|
|
105
|
+
return "gate=<custom>, val=<custom>"
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
class RaLU(nn.Module):
|
|
109
|
+
"""Kapısız Pure Rational aktivasyonu.
|
|
110
|
+
|
|
111
|
+
``f(x) = (x^3 + x) / (x^2 + 3)``
|
|
112
|
+
|
|
113
|
+
Şekil değiştirmez; tüm tensörlerde (``float16``/``bfloat16``/``float32``)
|
|
114
|
+
ve cihazlarda (CPU/CUDA/MPS) çalışır.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
def forward(self, x: Tensor) -> Tensor:
|
|
118
|
+
return fused_pure_rational(x)
|
|
119
|
+
|
|
120
|
+
def extra_repr(self) -> str:
|
|
121
|
+
return "inplace=False"
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: raglu
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Pure Rational GLU (RaGLU) and RaLU activations for PyTorch, Triton CUDA and Apple MLX.
|
|
5
|
+
Author: Ömer Faruk Solmaz
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: activation,glu,ralu,rational,pytorch,triton,mlx,deep-learning
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: torch>=2.0.0
|
|
24
|
+
Provides-Extra: triton
|
|
25
|
+
Requires-Dist: triton>=2.0.0; extra == "triton"
|
|
26
|
+
Provides-Extra: mlx
|
|
27
|
+
Requires-Dist: mlx>=0.1.0; extra == "mlx"
|
|
28
|
+
Provides-Extra: dev
|
|
29
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: build>=1.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: twine>=4.0.0; extra == "dev"
|
|
32
|
+
Dynamic: license-file
|
|
33
|
+
|
|
34
|
+
# RaGLU
|
|
35
|
+
|
|
36
|
+
**Pure Rational GLU (RaGLU)** ve **RaLU** aktivasyon fonksiyonları için platform
|
|
37
|
+
bağımsız PyTorch kütüphanesi. NVIDIA CUDA'da isteğe bağlı **Triton** çekirdekleri,
|
|
38
|
+
Apple Silicon'da ise yerel **MLX** desteği sunar.
|
|
39
|
+
|
|
40
|
+
Paket iki `nn.Module` sınıfı sunar:
|
|
41
|
+
|
|
42
|
+
| Sınıf | Görevi |
|
|
43
|
+
| --- | --- |
|
|
44
|
+
| `RaGLU()` | Kapılı (GLU) katman: `Linear` çıktısını gate/val olarak ikiye böler, `f(g) * v` uygular. |
|
|
45
|
+
| `RaLU()` | Kapısız, element-wise aktivasyon: `f(x)` uygular, şekli değiştirmez. |
|
|
46
|
+
|
|
47
|
+
## Fonksiyonlar
|
|
48
|
+
|
|
49
|
+
Kapılı (gated) varyant:
|
|
50
|
+
|
|
51
|
+
$$
|
|
52
|
+
\operatorname{RaGLU}(g, v) = \frac{g^3 + g}{g^2 + 3} \cdot v
|
|
53
|
+
$$
|
|
54
|
+
|
|
55
|
+
Kapısız varyant:
|
|
56
|
+
|
|
57
|
+
$$
|
|
58
|
+
\operatorname{RaLU}(x) = \frac{x^3 + x}{x^2 + 3}
|
|
59
|
+
$$
|
|
60
|
+
|
|
61
|
+
Türev (her iki varyantın çekirdeği):
|
|
62
|
+
|
|
63
|
+
$$
|
|
64
|
+
\frac{d}{dx}\left(\frac{x^3 + x}{x^2 + 3}\right)
|
|
65
|
+
= \frac{x^4 + 8x^2 + 3}{(x^2 + 3)^2}
|
|
66
|
+
$$
|
|
67
|
+
|
|
68
|
+
Fonksiyon tek (odd) bir fonksiyondur: `f(-x) = -f(x)`. Payda her zaman
|
|
69
|
+
`>= 3` olduğundan sayısal olarak kararlıdır.
|
|
70
|
+
|
|
71
|
+
## Kurulum
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install raglu
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
İsteğe bağlı hızlandırıcılar:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install "raglu[triton]" # NVIDIA CUDA için Triton çekirdekleri
|
|
81
|
+
pip install "raglu[mlx]" # Apple Silicon için MLX
|
|
82
|
+
pip install "raglu[dev]" # test + derleme araçları
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Kullanım
|
|
86
|
+
|
|
87
|
+
### Fonksiyonel PyTorch API
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
import torch
|
|
91
|
+
from raglu import fused_pure_rational_glu, fused_pure_rational
|
|
92
|
+
|
|
93
|
+
gate = torch.randn(32, 128)
|
|
94
|
+
val = torch.randn(32, 128)
|
|
95
|
+
|
|
96
|
+
y = fused_pure_rational_glu(gate, val) # (32, 128)
|
|
97
|
+
z = fused_pure_rational(gate) # (32, 128)
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`fused_pure_rational_glu`, CUDA + Triton mevcutsa füzyonlu çekirdeği kullanır.
|
|
101
|
+
Aksi halde otomatik olarak CPU/MPS uyumlu PyTorch fallback'ine döner.
|
|
102
|
+
Her iki yol da autograd desteklidir.
|
|
103
|
+
|
|
104
|
+
### Katmanlar
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
import torch
|
|
108
|
+
from raglu import RaGLU, RaLU
|
|
109
|
+
|
|
110
|
+
# Girdiyi 2 * out_features boyutuna genişletip gate/val olarak böler.
|
|
111
|
+
layer = RaGLU(in_features=768, out_features=768)
|
|
112
|
+
x = torch.randn(8, 128, 768)
|
|
113
|
+
y = layer(x) # (8, 128, 768)
|
|
114
|
+
|
|
115
|
+
# Kapısız aktivasyon
|
|
116
|
+
act = RaLU()
|
|
117
|
+
z = act(x) # (8, 128, 768)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Hazır `gate` ve `val` modülleri de kullanılabilir:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from torch import nn
|
|
124
|
+
from raglu import RaGLU
|
|
125
|
+
|
|
126
|
+
layer = RaGLU(
|
|
127
|
+
gate=nn.Linear(768, 1024),
|
|
128
|
+
val=nn.Linear(768, 1024),
|
|
129
|
+
)
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Apple MLX
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
import mlx.core as mx
|
|
136
|
+
from raglu import mlx_pure_rational_glu, mlx_pure_rational
|
|
137
|
+
|
|
138
|
+
gate = mx.random.normal((32, 128))
|
|
139
|
+
val = mx.random.normal((32, 128))
|
|
140
|
+
|
|
141
|
+
y = mlx_pure_rational_glu(gate, val)
|
|
142
|
+
z = mlx_pure_rational(gate)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
MLX kurulu değilse bu semboller dışa aktarılmaz; `raglu.HAS_MLX` ile kontrol
|
|
146
|
+
edebilirsiniz.
|
|
147
|
+
|
|
148
|
+
## API
|
|
149
|
+
|
|
150
|
+
| Sembol | Açıklama |
|
|
151
|
+
| --- | --- |
|
|
152
|
+
| `raglu.fused_pure_rational_glu(gate, val)` | Kapılı Pure Rational GLU (Triton/CUDA veya PyTorch fallback) |
|
|
153
|
+
| `raglu.fused_pure_rational(x)` | Kapısız RaLU aktivasyonu |
|
|
154
|
+
| `raglu.RaGLU` | Doğrusal katman + Pure Rational GLU `nn.Module`'ü |
|
|
155
|
+
| `raglu.RaLU` | Element-wise RaLU `nn.Module`'ü |
|
|
156
|
+
| `raglu.mlx_pure_rational_glu` | MLX kapılı varyant (MLX varsa) |
|
|
157
|
+
| `raglu.mlx_pure_rational` | MLX kapısız varyant (MLX varsa) |
|
|
158
|
+
| `raglu.HAS_TRITON` | Triton çekirdeklerinin kullanılabilirliği |
|
|
159
|
+
| `raglu.HAS_MLX` | MLX'in kullanılabilirliği |
|
|
160
|
+
|
|
161
|
+
### Not: CUDA clamp
|
|
162
|
+
|
|
163
|
+
Triton çekirdekleri sayısal kararlılık için kapı değerini `[-50, 50]` aralığına
|
|
164
|
+
kırpar. Bu aralığın dışındaki değerlerde Triton ve fallback çıktıları
|
|
165
|
+
farklılaşabilir; pratik aktivasyon girdilerinde fark yoktur.
|
|
166
|
+
|
|
167
|
+
## Geliştirme
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
git clone <repo-url>
|
|
171
|
+
cd RaGLU
|
|
172
|
+
python -m venv .venv
|
|
173
|
+
source .venv/bin/activate
|
|
174
|
+
pip install -e ".[dev]"
|
|
175
|
+
pytest -v
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Triton testleri yalnızca CUDA + Triton mevcut olduğunda, MLX testleri ise
|
|
179
|
+
yalnızca MLX kurulu olduğunda çalışır; diğer ortamlarda otomatik atlanır.
|
|
180
|
+
|
|
181
|
+
### Paket derleme
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
python -m build
|
|
185
|
+
python -m twine check dist/*
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## Lisans
|
|
189
|
+
|
|
190
|
+
MIT — bkz. [LICENSE](LICENSE).
|
|
191
|
+
|
|
192
|
+
Copyright (c) 2026 Ömer Faruk Solmaz
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
raglu/__init__.py
|
|
5
|
+
raglu/core.py
|
|
6
|
+
raglu/py.typed
|
|
7
|
+
raglu/torch_module.py
|
|
8
|
+
raglu.egg-info/PKG-INFO
|
|
9
|
+
raglu.egg-info/SOURCES.txt
|
|
10
|
+
raglu.egg-info/dependency_links.txt
|
|
11
|
+
raglu.egg-info/requires.txt
|
|
12
|
+
raglu.egg-info/top_level.txt
|
|
13
|
+
tests/test_raglu.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
raglu
|
raglu-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"""RaGLU testleri: PyTorch autograd, Triton ve MLX doğrulaması."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
import torch
|
|
7
|
+
|
|
8
|
+
import raglu
|
|
9
|
+
from raglu import (
|
|
10
|
+
HAS_MLX,
|
|
11
|
+
HAS_TRITON,
|
|
12
|
+
RaGLU,
|
|
13
|
+
RaLU,
|
|
14
|
+
fused_pure_rational,
|
|
15
|
+
fused_pure_rational_glu,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _reference_rational(x: torch.Tensor) -> torch.Tensor:
|
|
20
|
+
x_sq = x * x
|
|
21
|
+
return (x * x_sq + x) / (x_sq + 3.0)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _reference_glu(gate: torch.Tensor, val: torch.Tensor) -> torch.Tensor:
|
|
25
|
+
return _reference_rational(gate) * val
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# ==============================================================================
|
|
29
|
+
# PyTorch fallback: ileri yön
|
|
30
|
+
# ==============================================================================
|
|
31
|
+
def test_ralu_matches_reference():
|
|
32
|
+
torch.manual_seed(0)
|
|
33
|
+
x = torch.randn(1024, dtype=torch.float64)
|
|
34
|
+
out = fused_pure_rational(x)
|
|
35
|
+
assert torch.allclose(out, _reference_rational(x), atol=1e-12, rtol=1e-12)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_raglu_matches_reference():
|
|
39
|
+
torch.manual_seed(0)
|
|
40
|
+
gate = torch.randn(64, 128, dtype=torch.float64)
|
|
41
|
+
val = torch.randn(64, 128, dtype=torch.float64)
|
|
42
|
+
out = fused_pure_rational_glu(gate, val)
|
|
43
|
+
assert torch.allclose(out, _reference_glu(gate, val), atol=1e-12, rtol=1e-12)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.mark.parametrize("dtype", [torch.float32, torch.float64])
|
|
47
|
+
def test_shapes_and_dtypes_preserved(dtype):
|
|
48
|
+
gate = torch.randn(3, 5, 7, dtype=dtype)
|
|
49
|
+
val = torch.randn(3, 5, 7, dtype=dtype)
|
|
50
|
+
out = fused_pure_rational_glu(gate, val)
|
|
51
|
+
assert out.shape == gate.shape
|
|
52
|
+
assert out.dtype == dtype
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@pytest.mark.skipif(not torch.backends.mps.is_available(), reason="MPS yok")
|
|
56
|
+
def test_mps_fallback_forward_backward():
|
|
57
|
+
gate = torch.randn(4, 8, device="mps", requires_grad=True)
|
|
58
|
+
val = torch.randn(4, 8, device="mps", requires_grad=True)
|
|
59
|
+
out = fused_pure_rational_glu(gate, val)
|
|
60
|
+
assert out.device.type == "mps"
|
|
61
|
+
out.sum().backward()
|
|
62
|
+
assert gate.grad is not None and torch.isfinite(gate.grad).all()
|
|
63
|
+
assert val.grad is not None and torch.isfinite(val.grad).all()
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_odd_and_empty_sizes():
|
|
67
|
+
# Triton çekirdeğinin maskeleme sınırları ve boş tensörler.
|
|
68
|
+
gate = torch.randn(1023, dtype=torch.float64)
|
|
69
|
+
val = torch.randn(1023, dtype=torch.float64)
|
|
70
|
+
assert torch.allclose(
|
|
71
|
+
fused_pure_rational_glu(gate, val), _reference_glu(gate, val), atol=1e-12
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
empty = torch.empty(0, dtype=torch.float64)
|
|
75
|
+
out = fused_pure_rational_glu(empty, empty)
|
|
76
|
+
assert out.shape == (0,)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_function_is_odd():
|
|
80
|
+
# f(-x) = -f(x) olduğundan aktivasyon tek fonksiyondur.
|
|
81
|
+
x = torch.linspace(-5.0, 5.0, 101, dtype=torch.float64)
|
|
82
|
+
assert torch.allclose(fused_pure_rational(-x), -fused_pure_rational(x), atol=1e-12)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
# ==============================================================================
|
|
86
|
+
# Gradyan doğrulaması (torch.autograd.gradcheck)
|
|
87
|
+
# ==============================================================================
|
|
88
|
+
def test_ralu_gradcheck():
|
|
89
|
+
x = torch.randn(16, 16, dtype=torch.float64, requires_grad=True)
|
|
90
|
+
assert torch.autograd.gradcheck(fused_pure_rational, (x,), eps=1e-6, atol=1e-5)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def test_raglu_gradcheck():
|
|
94
|
+
gate = torch.randn(16, 16, dtype=torch.float64, requires_grad=True)
|
|
95
|
+
val = torch.randn(16, 16, dtype=torch.float64, requires_grad=True)
|
|
96
|
+
assert torch.autograd.gradcheck(
|
|
97
|
+
fused_pure_rational_glu, (gate, val), eps=1e-6, atol=1e-5
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def test_raglu_gradcheck_non_contiguous():
|
|
102
|
+
gate = torch.randn(32, 32, dtype=torch.float64, requires_grad=True).t()
|
|
103
|
+
val = torch.randn(32, 32, dtype=torch.float64, requires_grad=True).t()
|
|
104
|
+
assert torch.autograd.gradcheck(
|
|
105
|
+
fused_pure_rational_glu, (gate, val), eps=1e-6, atol=1e-5
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def test_raglu_backward_formula():
|
|
110
|
+
x = torch.linspace(-3.0, 3.0, 101, dtype=torch.float64, requires_grad=True)
|
|
111
|
+
fused_pure_rational(x).sum().backward()
|
|
112
|
+
# df/dx = (x^4 + 8x^2 + 3) / (x^2 + 3)^2
|
|
113
|
+
x_sq = x.detach() ** 2
|
|
114
|
+
expected = (x_sq**2 + 8.0 * x_sq + 3.0) / (x_sq + 3.0) ** 2
|
|
115
|
+
assert torch.allclose(x.grad, expected, atol=1e-12, rtol=1e-12)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# ==============================================================================
|
|
119
|
+
# nn.Module katmanları
|
|
120
|
+
# ==============================================================================
|
|
121
|
+
def test_ralu_module_shape_and_grad():
|
|
122
|
+
layer = RaLU()
|
|
123
|
+
x = torch.randn(4, 8, requires_grad=True)
|
|
124
|
+
out = layer(x)
|
|
125
|
+
assert out.shape == x.shape
|
|
126
|
+
out.sum().backward()
|
|
127
|
+
assert x.grad is not None
|
|
128
|
+
assert torch.isfinite(x.grad).all()
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def test_raglu_module_default_out_features():
|
|
132
|
+
layer = RaGLU(16)
|
|
133
|
+
x = torch.randn(2, 3, 16)
|
|
134
|
+
out = layer(x)
|
|
135
|
+
assert out.shape == (2, 3, 16)
|
|
136
|
+
assert layer.linear.weight.shape == (32, 16)
|
|
137
|
+
assert "in_features=16" in repr(layer)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def test_raglu_module_projection():
|
|
141
|
+
layer = RaGLU(16, 32, bias=False)
|
|
142
|
+
x = torch.randn(5, 16)
|
|
143
|
+
out = layer(x)
|
|
144
|
+
assert out.shape == (5, 32)
|
|
145
|
+
assert layer.linear.bias is None
|
|
146
|
+
assert sum(p.numel() for p in layer.parameters()) == 2 * 32 * 16
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def test_raglu_module_matches_manual_computation():
|
|
150
|
+
torch.manual_seed(0)
|
|
151
|
+
layer = RaGLU(8, 4).double()
|
|
152
|
+
x = torch.randn(6, 8, dtype=torch.float64)
|
|
153
|
+
linear_out = layer.linear(x)
|
|
154
|
+
gate, val = linear_out.chunk(2, dim=-1)
|
|
155
|
+
expected = _reference_glu(gate, val)
|
|
156
|
+
assert torch.allclose(layer(x), expected, atol=1e-12)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def test_raglu_module_custom_gate_val():
|
|
160
|
+
gate = torch.nn.Linear(8, 12, bias=False)
|
|
161
|
+
val = torch.nn.Linear(8, 12, bias=False)
|
|
162
|
+
layer = RaGLU(gate=gate, val=val)
|
|
163
|
+
x = torch.randn(3, 8)
|
|
164
|
+
assert layer(x).shape == (3, 12)
|
|
165
|
+
assert layer.linear is None
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def test_raglu_module_gradcheck():
|
|
169
|
+
torch.manual_seed(0)
|
|
170
|
+
layer = RaGLU(4, 3).double()
|
|
171
|
+
x = torch.randn(5, 4, dtype=torch.float64, requires_grad=True)
|
|
172
|
+
assert torch.autograd.gradcheck(lambda t: layer(t), (x,), eps=1e-6, atol=1e-5)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def test_raglu_module_validation():
|
|
176
|
+
with pytest.raises(ValueError):
|
|
177
|
+
RaGLU()
|
|
178
|
+
with pytest.raises(ValueError):
|
|
179
|
+
RaGLU(gate=torch.nn.Linear(4, 4))
|
|
180
|
+
with pytest.raises(ValueError):
|
|
181
|
+
RaGLU(4, gate=torch.nn.Linear(4, 4), val=torch.nn.Linear(4, 4))
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def test_raglu_module_mismatched_custom_shapes():
|
|
185
|
+
layer = RaGLU(
|
|
186
|
+
gate=torch.nn.Linear(4, 8, bias=False),
|
|
187
|
+
val=torch.nn.Linear(4, 7, bias=False),
|
|
188
|
+
)
|
|
189
|
+
with pytest.raises(ValueError):
|
|
190
|
+
layer(torch.randn(2, 4))
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def test_package_exports():
|
|
194
|
+
assert raglu.__version__ == "0.1.0"
|
|
195
|
+
for name in (
|
|
196
|
+
"fused_pure_rational_glu",
|
|
197
|
+
"fused_pure_rational",
|
|
198
|
+
"RaGLU",
|
|
199
|
+
"RaLU",
|
|
200
|
+
"HAS_TRITON",
|
|
201
|
+
"HAS_MLX",
|
|
202
|
+
):
|
|
203
|
+
assert hasattr(raglu, name)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
# ==============================================================================
|
|
207
|
+
# Triton fused kernel doğrulaması (yalnızca CUDA + Triton varsa)
|
|
208
|
+
# ==============================================================================
|
|
209
|
+
@pytest.mark.skipif(not (HAS_TRITON and torch.cuda.is_available()), reason="CUDA/Triton yok")
|
|
210
|
+
def test_triton_forward_matches_fallback():
|
|
211
|
+
torch.manual_seed(0)
|
|
212
|
+
device = torch.device("cuda")
|
|
213
|
+
# Clamp sınırı olan +/-50'nin oldukça altında değerler kullanılır.
|
|
214
|
+
gate = torch.randn(4096, device=device) * 3.0
|
|
215
|
+
val = torch.randn(4096, device=device)
|
|
216
|
+
|
|
217
|
+
fused = fused_pure_rational_glu(gate, val)
|
|
218
|
+
g_sq = gate * gate
|
|
219
|
+
fallback = ((gate * g_sq + gate) / (g_sq + 3.0)) * val
|
|
220
|
+
|
|
221
|
+
assert torch.allclose(fused, fallback, atol=1e-4, rtol=1e-4)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
@pytest.mark.skipif(not (HAS_TRITON and torch.cuda.is_available()), reason="CUDA/Triton yok")
|
|
225
|
+
def test_triton_backward_matches_autograd():
|
|
226
|
+
torch.manual_seed(1)
|
|
227
|
+
device = torch.device("cuda")
|
|
228
|
+
gate_f = (torch.randn(4096, device=device) * 3.0).requires_grad_(True)
|
|
229
|
+
val_f = torch.randn(4096, device=device, requires_grad=True)
|
|
230
|
+
gate_r = gate_f.detach().clone().requires_grad_(True)
|
|
231
|
+
val_r = val_f.detach().clone().requires_grad_(True)
|
|
232
|
+
dy = torch.randn(4096, device=device)
|
|
233
|
+
|
|
234
|
+
# Fused yol
|
|
235
|
+
fused = raglu.core.FusedPureRationalGLUFunction.apply(gate_f, val_f)
|
|
236
|
+
dg_f, dv_f = torch.autograd.grad(fused, (gate_f, val_f), grad_outputs=dy)
|
|
237
|
+
|
|
238
|
+
# Referans yol
|
|
239
|
+
out_r = _reference_glu(gate_r, val_r)
|
|
240
|
+
dg_r, dv_r = torch.autograd.grad(out_r, (gate_r, val_r), grad_outputs=dy)
|
|
241
|
+
|
|
242
|
+
assert torch.allclose(fused.detach(), out_r.detach(), atol=1e-4, rtol=1e-4)
|
|
243
|
+
assert torch.allclose(dg_f, dg_r, atol=1e-4, rtol=1e-4)
|
|
244
|
+
assert torch.allclose(dv_f, dv_r, atol=1e-4, rtol=1e-4)
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
@pytest.mark.skipif(not (HAS_TRITON and torch.cuda.is_available()), reason="CUDA/Triton yok")
|
|
248
|
+
def test_triton_non_contiguous_inputs():
|
|
249
|
+
torch.manual_seed(2)
|
|
250
|
+
device = torch.device("cuda")
|
|
251
|
+
gate = (torch.randn(64, 64, device=device) * 2.0).t().requires_grad_(True)
|
|
252
|
+
val = torch.randn(64, 64, device=device).t().requires_grad_(True)
|
|
253
|
+
out = fused_pure_rational_glu(gate, val)
|
|
254
|
+
out.sum().backward()
|
|
255
|
+
assert torch.isfinite(gate.grad).all()
|
|
256
|
+
assert torch.isfinite(val.grad).all()
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
# ==============================================================================
|
|
260
|
+
# MLX doğrulaması (yalnızca MLX kuruluysa)
|
|
261
|
+
# ==============================================================================
|
|
262
|
+
@pytest.mark.skipif(not HAS_MLX, reason="MLX kurulu değil")
|
|
263
|
+
def test_mlx_matches_pytorch():
|
|
264
|
+
import mlx.core as mx
|
|
265
|
+
import numpy as np
|
|
266
|
+
|
|
267
|
+
gate_np = np.random.default_rng(0).standard_normal((32, 32)).astype(np.float32)
|
|
268
|
+
val_np = np.random.default_rng(1).standard_normal((32, 32)).astype(np.float32)
|
|
269
|
+
|
|
270
|
+
mx_out = raglu.mlx_pure_rational_glu(mx.array(gate_np), mx.array(val_np))
|
|
271
|
+
mx_out = np.array(mx_out)
|
|
272
|
+
|
|
273
|
+
pt_out = fused_pure_rational_glu(
|
|
274
|
+
torch.from_numpy(gate_np), torch.from_numpy(val_np)
|
|
275
|
+
).numpy()
|
|
276
|
+
|
|
277
|
+
assert np.allclose(mx_out, pt_out, atol=1e-5, rtol=1e-5)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
@pytest.mark.skipif(not HAS_MLX, reason="MLX kurulu değil")
|
|
281
|
+
def test_mlx_ralu_values():
|
|
282
|
+
import mlx.core as mx
|
|
283
|
+
import numpy as np
|
|
284
|
+
|
|
285
|
+
x_np = np.linspace(-4.0, 4.0, 101, dtype=np.float32)
|
|
286
|
+
mx_out = np.array(raglu.mlx_pure_rational(mx.array(x_np)))
|
|
287
|
+
x_sq = x_np * x_np
|
|
288
|
+
expected = (x_np * x_sq + x_np) / (x_sq + 3.0)
|
|
289
|
+
assert np.allclose(mx_out, expected, atol=1e-6)
|