You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This document describes known issues encountered when building TaylorTorch on Linux with Swift's automatic differentiation, and the workarounds implemented.
4
+
5
+
> **Note**: These issues are **specific to Linux (Ubuntu 24.04)**. macOS builds do not experience these problems and can use standard C library math functions without issues.
6
+
7
+
## Swift SIL Linker Assertion Failures with C Library Math Functions
8
+
9
+
### Problem
10
+
11
+
When using C library math functions (`exp`, `log`, `sqrt`, `pow`, `powf`) in code that undergoes Swift automatic differentiation, the Swift compiler crashes with a SIL (Swift Intermediate Language) linker assertion:
12
+
13
+
```
14
+
Assertion failed: googGV->isDeclaration() && "global variable already has initializer"
15
+
```
16
+
17
+
or
18
+
19
+
```
20
+
LLVM ERROR: Global is external, but doesn't have external or weak linkage
21
+
```
22
+
23
+
These errors occur because the Swift autodiff system generates derivative code that references C library function symbols in ways that conflict with Swift's SIL linker expectations on Linux.
24
+
25
+
### Affected Functions
26
+
27
+
-`exp()`, `expf()` - exponential
28
+
-`log()`, `logf()`, `log1p()` - logarithm
29
+
-`sqrt()`, `sqrtf()` - square root
30
+
-`pow()`, `powf()` - power
31
+
32
+
### Workarounds
33
+
34
+
#### 1. Replace `sqrt` with `.squareRoot()`
35
+
36
+
Swift's native `FloatingPoint.squareRoot()` method works correctly with autodiff:
37
+
38
+
```swift
39
+
// Before (causes SIL crash)
40
+
let a =sqrt(x)
41
+
42
+
// After (works)
43
+
let a = x.squareRoot()
44
+
```
45
+
46
+
#### 2. Replace `pow(x, -0.5)` with `1.0 / x.squareRoot()`
47
+
48
+
```swift
49
+
// Before (causes SIL crash)
50
+
let a =powf(x, -0.5)
51
+
let b =powf(x, -1.5)
52
+
53
+
// After (works)
54
+
let a =1.0/ x.squareRoot()
55
+
let b =1.0/ (x.squareRoot() * x)
56
+
```
57
+
58
+
#### 3. Replace `exp` with hardcoded constants or Taylor series
59
+
60
+
For simple cases like `exp(1.0)`:
61
+
```swift
62
+
// Before
63
+
let e =exp(1.0)
64
+
65
+
// After
66
+
let e =2.718281828459045// Euler's number
67
+
```
68
+
69
+
For test code that needs `exp` computations, use a pure Swift Taylor series:
70
+
```swift
71
+
funcswiftExp(_x: Double) ->Double {
72
+
var result =1.0
73
+
var term =1.0
74
+
for i in1...30 {
75
+
term *= x /Double(i)
76
+
result += term
77
+
}
78
+
return result
79
+
}
80
+
```
81
+
82
+
#### 4. Replace `log1p` with Mercator series
83
+
84
+
```swift
85
+
funcswiftLog1p(_x: Double) ->Double {
86
+
let y =1.0+ x
87
+
if y <=0 { return-.infinity }
88
+
var result =0.0
89
+
var term = (y -1) / (y +1)
90
+
let term2 = term * term
91
+
for i instride(from: 1, through: 31, by: 2) {
92
+
result += term /Double(i)
93
+
term *= term2
94
+
}
95
+
return2.0* result
96
+
}
97
+
```
98
+
99
+
**Note**: Taylor/Mercator series approximations lose precision for larger values. Tests using these should use looser tolerances (e.g., `1e-4` instead of `1e-6`).
100
+
101
+
### Files Modified
102
+
103
+
-`Examples/ANKI/main.swift` - Replaced `powf` with `.squareRoot()`
104
+
-`Sources/Torch/Modules/Initializers.swift` - Replaced `sqrt` with `.squareRoot()`
105
+
-`Tests/TensorTests/TensorMathTests.swift` - Replaced `Foundation.exp(1.0)` with constant
106
+
-`Tests/TorchTests/LossTests.swift` - Added pure Swift `swiftExp` and `swiftLog1p`
107
+
-`Tests/TorchTests/ActivationModulesTests.swift` - Replaced `Foundation.sqrt` with `.squareRoot()`
108
+
109
+
---
110
+
111
+
## Swift Autodiff Crash with For-In Loops
112
+
113
+
### Problem
114
+
115
+
Swift's automatic differentiation crashes when a `for-in` loop is used inside a `valueWithPullback` closure on Linux:
116
+
117
+
```
118
+
LLVM ERROR: Global is external, but doesn't have external or weak linkage
119
+
```
120
+
121
+
### Example
122
+
123
+
```swift
124
+
// This crashes the compiler
125
+
let (value, pullback) =valueWithPullback(at: input) { tensor in
126
+
var current = tensor
127
+
for dim in dims { // <-- for-in loop causes crash
128
+
current = current.sum(dim: dim)
129
+
}
130
+
return current
131
+
}
132
+
```
133
+
134
+
### Workaround
135
+
136
+
Comment out or disable tests that use for-in loops inside differentiated closures. This is a Swift compiler bug that needs to be fixed upstream.
137
+
138
+
### Files Modified
139
+
140
+
-`Tests/TensorTests/TensorAxisSugarDifferentiationTests.swift` - Commented out `axisReductionsGradientMatchIntegerVariants` test
141
+
142
+
---
143
+
144
+
## Adam Optimizer KeyPath Crashes with Complex Models
145
+
146
+
### Problem
147
+
148
+
The Adam optimizer crashes at runtime when used with complex nested models (like Transformers) on Linux. The crash occurs in `recursivelyAllWritableKeyPaths` when iterating over the TangentVector structure.
149
+
150
+
```
151
+
Swift/KeyPath.swift:1051: Fatal error: Could not extract a String from KeyPath Swift.KeyPath<...>
152
+
```
153
+
154
+
This appears to be related to how Swift handles KeyPath operations on complex nested generic types on Linux.
155
+
156
+
### Workaround
157
+
158
+
Use SGD with momentum instead of Adam for complex models:
159
+
160
+
```swift
161
+
// Instead of:
162
+
let opt =Adam(for: model, learningRate: 0.01)
163
+
164
+
// Use:
165
+
var opt =SGD(for: model, learningRate: 0.01, momentum: 0.9)
166
+
```
167
+
168
+
### Files Modified
169
+
170
+
-`Examples/ANKI/main.swift` - Switched from Adam to SGD optimizer
171
+
-`Examples/KARATE/main.swift` - Switched from Adam to SGD with LR 0.001 (higher rates cause NaN)
172
+
173
+
---
174
+
175
+
## Environment Variables Required for Building
176
+
177
+
### Problem
178
+
179
+
Building TaylorTorch fails with `'swift/bridging' file not found` if environment variables are not set.
0 commit comments