Skip to content

Commit 44823ac

Browse files
Fix Base64 import and make system info gathering robust
Add missing Base64 import to fix base64encode error in telemetry.jl. Completely rewrite system information gathering with comprehensive try-catch blocks around all system introspection calls. All system info fields now gracefully degrade to "unknown" when: - System calls fail - Julia internals are unavailable - Hardware detection fails - Package availability checks error Changes: - Add using Base64 to fix base64encode UndefVarError - Wrap all Sys.* calls in try-catch with "unknown" fallbacks - Wrap all LinearAlgebra/BLAS calls in try-catch - Wrap all LinearSolve package checks in try-catch - Replace missing values with "unknown" strings - Ensure system info collection never crashes the autotune Fixes UndefVarError: base64encode not defined in LinearSolveAutotune Makes autotune robust across all Julia versions and system configurations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 3d5093a commit 44823ac

File tree

2 files changed

+139
-37
lines changed

2 files changed

+139
-37
lines changed

lib/LinearSolveAutotune/src/LinearSolveAutotune.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ using Random
1111
using LinearAlgebra
1212
using Printf
1313
using Dates
14+
using Base64
1415
using RecursiveFactorization # Hard dependency to ensure RFLUFactorization is available
1516

1617
# Optional dependencies for telemetry and plotting

lib/LinearSolveAutotune/src/gpu_detection.jl

Lines changed: 138 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -109,51 +109,138 @@ function get_detailed_system_info()
109109
# Basic system information
110110
system_data = Dict{String, Any}()
111111

112-
# Julia and system basics
113-
system_data["timestamp"] = string(Dates.now())
114-
system_data["julia_version"] = string(VERSION)
115-
system_data["julia_commit"] = Base.GIT_VERSION_INFO.commit[1:10] # Short commit hash
116-
system_data["os_name"] = Sys.iswindows() ? "Windows" : Sys.islinux() ? "Linux" : Sys.isapple() ? "macOS" : "Other"
117-
system_data["os_version"] = string(Sys.KERNEL)
118-
system_data["architecture"] = string(Sys.ARCH)
119-
system_data["cpu_cores"] = Sys.CPU_THREADS
120-
system_data["julia_threads"] = Threads.nthreads()
121-
system_data["word_size"] = Sys.WORD_SIZE
122-
system_data["machine"] = Sys.MACHINE
112+
# Julia and system basics - all with safe fallbacks
113+
try
114+
system_data["timestamp"] = string(Dates.now())
115+
catch
116+
system_data["timestamp"] = "unknown"
117+
end
118+
119+
try
120+
system_data["julia_version"] = string(VERSION)
121+
catch
122+
system_data["julia_version"] = "unknown"
123+
end
124+
125+
try
126+
system_data["julia_commit"] = Base.GIT_VERSION_INFO.commit[1:10] # Short commit hash
127+
catch
128+
system_data["julia_commit"] = "unknown"
129+
end
130+
131+
try
132+
system_data["os_name"] = Sys.iswindows() ? "Windows" : Sys.islinux() ? "Linux" : Sys.isapple() ? "macOS" : "Other"
133+
catch
134+
system_data["os_name"] = "unknown"
135+
end
136+
137+
try
138+
system_data["os_version"] = string(Sys.KERNEL)
139+
catch
140+
system_data["os_version"] = "unknown"
141+
end
142+
143+
try
144+
system_data["architecture"] = string(Sys.ARCH)
145+
catch
146+
system_data["architecture"] = "unknown"
147+
end
148+
149+
try
150+
system_data["cpu_cores"] = Sys.CPU_THREADS
151+
catch
152+
system_data["cpu_cores"] = "unknown"
153+
end
154+
155+
try
156+
system_data["julia_threads"] = Threads.nthreads()
157+
catch
158+
system_data["julia_threads"] = "unknown"
159+
end
160+
161+
try
162+
system_data["word_size"] = Sys.WORD_SIZE
163+
catch
164+
system_data["word_size"] = "unknown"
165+
end
166+
167+
try
168+
system_data["machine"] = Sys.MACHINE
169+
catch
170+
system_data["machine"] = "unknown"
171+
end
123172

124173
# CPU details
125-
cpu_info = Sys.cpu_info()[1]
126-
system_data["cpu_name"] = cpu_info.model
127-
system_data["cpu_speed_mhz"] = cpu_info.speed
174+
try
175+
cpu_info = Sys.cpu_info()[1]
176+
system_data["cpu_name"] = cpu_info.model
177+
system_data["cpu_speed_mhz"] = cpu_info.speed
178+
catch
179+
system_data["cpu_name"] = "unknown"
180+
system_data["cpu_speed_mhz"] = "unknown"
181+
end
128182

129183
# Categorize CPU vendor for easy analysis
130-
cpu_name_lower = lowercase(system_data["cpu_name"])
131-
if contains(cpu_name_lower, "intel")
132-
system_data["cpu_vendor"] = "Intel"
133-
elseif contains(cpu_name_lower, "amd")
134-
system_data["cpu_vendor"] = "AMD"
135-
elseif contains(cpu_name_lower, "apple") || contains(cpu_name_lower, "m1") || contains(cpu_name_lower, "m2") || contains(cpu_name_lower, "m3")
136-
system_data["cpu_vendor"] = "Apple"
137-
else
138-
system_data["cpu_vendor"] = "Other"
184+
try
185+
cpu_name_lower = lowercase(string(system_data["cpu_name"]))
186+
if contains(cpu_name_lower, "intel")
187+
system_data["cpu_vendor"] = "Intel"
188+
elseif contains(cpu_name_lower, "amd")
189+
system_data["cpu_vendor"] = "AMD"
190+
elseif contains(cpu_name_lower, "apple") || contains(cpu_name_lower, "m1") || contains(cpu_name_lower, "m2") || contains(cpu_name_lower, "m3")
191+
system_data["cpu_vendor"] = "Apple"
192+
else
193+
system_data["cpu_vendor"] = "Other"
194+
end
195+
catch
196+
system_data["cpu_vendor"] = "unknown"
139197
end
140198

141199
# BLAS and linear algebra libraries
142-
system_data["blas_vendor"] = string(LinearAlgebra.BLAS.vendor())
200+
try
201+
system_data["blas_vendor"] = string(LinearAlgebra.BLAS.vendor())
202+
catch
203+
system_data["blas_vendor"] = "unknown"
204+
end
205+
143206
# LAPACK vendor detection (safe for different Julia versions)
144207
try
145208
system_data["lapack_vendor"] = string(LinearAlgebra.LAPACK.vendor())
146209
catch
147210
# Fallback: LAPACK vendor often matches BLAS vendor
148-
system_data["lapack_vendor"] = system_data["blas_vendor"]
211+
system_data["lapack_vendor"] = get(system_data, "blas_vendor", "unknown")
212+
end
213+
214+
try
215+
system_data["blas_num_threads"] = LinearAlgebra.BLAS.get_num_threads()
216+
catch
217+
system_data["blas_num_threads"] = "unknown"
149218
end
150-
system_data["blas_num_threads"] = LinearAlgebra.BLAS.get_num_threads()
151219

152220
# LinearSolve-specific package availability
153-
system_data["mkl_available"] = LinearSolve.usemkl
154-
system_data["mkl_used"] = system_data["mkl_available"] && contains(lowercase(system_data["blas_vendor"]), "mkl")
155-
system_data["apple_accelerate_available"] = LinearSolve.appleaccelerate_isavailable()
156-
system_data["apple_accelerate_used"] = system_data["apple_accelerate_available"] && contains(lowercase(system_data["blas_vendor"]), "accelerate")
221+
try
222+
system_data["mkl_available"] = LinearSolve.usemkl
223+
catch
224+
system_data["mkl_available"] = false
225+
end
226+
227+
try
228+
system_data["mkl_used"] = system_data["mkl_available"] && contains(lowercase(string(system_data["blas_vendor"])), "mkl")
229+
catch
230+
system_data["mkl_used"] = false
231+
end
232+
233+
try
234+
system_data["apple_accelerate_available"] = LinearSolve.appleaccelerate_isavailable()
235+
catch
236+
system_data["apple_accelerate_available"] = false
237+
end
238+
239+
try
240+
system_data["apple_accelerate_used"] = system_data["apple_accelerate_available"] && contains(lowercase(string(system_data["blas_vendor"])), "accelerate")
241+
catch
242+
system_data["apple_accelerate_used"] = false
243+
end
157244

158245
# BLIS availability check
159246
system_data["blis_available"] = false
@@ -163,15 +250,24 @@ function get_detailed_system_info()
163250
if isdefined(LinearSolve, :BLISLUFactorization) && hasmethod(LinearSolve.BLISLUFactorization, ())
164251
system_data["blis_available"] = true
165252
# Check if BLIS is actually being used (contains "blis" in BLAS vendor)
166-
system_data["blis_used"] = contains(lowercase(system_data["blas_vendor"]), "blis")
253+
system_data["blis_used"] = contains(lowercase(string(system_data["blas_vendor"])), "blis")
167254
end
168255
catch
169256
# If there's any error checking BLIS, leave as false
170257
end
171258

172259
# GPU information
173-
system_data["cuda_available"] = is_cuda_available()
174-
system_data["metal_available"] = is_metal_available()
260+
try
261+
system_data["cuda_available"] = is_cuda_available()
262+
catch
263+
system_data["cuda_available"] = false
264+
end
265+
266+
try
267+
system_data["metal_available"] = is_metal_available()
268+
catch
269+
system_data["metal_available"] = false
270+
end
175271

176272
# Try to detect if CUDA/Metal packages are actually loaded
177273
system_data["cuda_loaded"] = false
@@ -189,7 +285,12 @@ function get_detailed_system_info()
189285
end
190286

191287
# Environment information
192-
system_data["libm"] = Base.libm_name
288+
try
289+
system_data["libm"] = Base.libm_name
290+
catch
291+
system_data["libm"] = "unknown"
292+
end
293+
193294
# libdl_name may not exist in all Julia versions
194295
try
195296
system_data["libdl"] = Base.libdl_name
@@ -205,16 +306,16 @@ function get_detailed_system_info()
205306
if mem_match !== nothing
206307
system_data["total_memory_gb"] = round(parse(Int, mem_match.captures[1]) / 1024 / 1024, digits=2)
207308
else
208-
system_data["total_memory_gb"] = missing
309+
system_data["total_memory_gb"] = "unknown"
209310
end
210311
elseif Sys.isapple()
211312
mem_bytes = parse(Int, read(`sysctl -n hw.memsize`, String))
212313
system_data["total_memory_gb"] = round(mem_bytes / 1024^3, digits=2)
213314
else
214-
system_data["total_memory_gb"] = missing
315+
system_data["total_memory_gb"] = "unknown"
215316
end
216317
catch
217-
system_data["total_memory_gb"] = missing
318+
system_data["total_memory_gb"] = "unknown"
218319
end
219320

220321
# Create DataFrame with single row

0 commit comments

Comments
 (0)