Skip to content

Commit 3bd5492

Browse files
committed
add blas logging for apple, mkl, openblas
1 parent 51254c5 commit 3bd5492

File tree

4 files changed

+316
-1
lines changed

4 files changed

+316
-1
lines changed

src/appleaccelerate.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,12 +255,45 @@ function SciMLBase.solve!(cache::LinearCache, alg::AppleAccelerateLUFactorizatio
255255
error("Error, AppleAccelerate binary is missing but solve is being called. Report this issue")
256256
A = cache.A
257257
A = convert(AbstractMatrix, A)
258+
verbose = cache.verbose
258259
if cache.isfresh
259260
cacheval = @get_cacheval(cache, :AppleAccelerateLUFactorization)
260261
res = aa_getrf!(A; ipiv = cacheval[1].ipiv, info = cacheval[2])
261262
fact = LU(res[1:3]...), res[4]
262263
cache.cacheval = fact
263264

265+
info_value = res[3]
266+
267+
if info_value != 0
268+
if !isa(verbose.blas_info, SciMLLogging.Silent) || !isa(verbose.blas_errors, SciMLLogging.Silent) ||
269+
!isa(verbose.blas_invalid_args, SciMLLogging.Silent)
270+
op_info = get_blas_operation_info(:dgetrf, A, cache.b, condition = !isa(verbose.condition_number, SciMLLogging.Silent))
271+
@SciMLMessage(cache.verbose, :condition_number) do
272+
if op_info[:condition_number] === nothing
273+
return "Matrix condition number calculation failed."
274+
else
275+
return "Matrix condition number: $(round(op_info[:condition_number], sigdigits=4)) for $(size(A, 1))×$(size(A, 2)) matrix in dgetrf"
276+
end
277+
end
278+
verb_option, message = blas_info_msg(
279+
:dgetrf, info_value; extra_context = op_info)
280+
@SciMLMessage(message, verbose, verb_option)
281+
end
282+
else
283+
@SciMLMessage(cache.verbose, :blas_success) do
284+
op_info = get_blas_operation_info(:dgetrf, A, cache.b,
285+
condition = !isa(verbose.condition_number, SciMLLogging.Silent))
286+
@SciMLMessage(cache.verbose, :condition_number) do
287+
if op_info[:condition_number] === nothing
288+
return "Matrix condition number calculation failed."
289+
else
290+
return "Matrix condition number: $(round(op_info[:condition_number], sigdigits=4)) for $(size(A, 1))×$(size(A, 2)) matrix in dgetrf"
291+
end
292+
end
293+
return "BLAS LU factorization (dgetrf) completed successfully for $(op_info[:matrix_size]) matrix"
294+
end
295+
end
296+
264297
if !LinearAlgebra.issuccess(fact[1])
265298
return SciMLBase.build_linear_solution(
266299
alg, cache.u, nothing, cache; retcode = ReturnCode.Failure)

src/mkl.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,45 @@ function SciMLBase.solve!(cache::LinearCache, alg::MKLLUFactorization;
239239
error("Error, MKL binary is missing but solve is being called. Report this issue")
240240
A = cache.A
241241
A = convert(AbstractMatrix, A)
242+
verbose = cache.verbose
242243
if cache.isfresh
243244
cacheval = @get_cacheval(cache, :MKLLUFactorization)
244245
res = getrf!(A; ipiv = cacheval[1].ipiv, info = cacheval[2])
245246
fact = LU(res[1:3]...), res[4]
246247
cache.cacheval = fact
247248

249+
info_value = res[3]
250+
251+
if info_value != 0
252+
if !isa(verbose.blas_info, SciMLLogging.Silent) || !isa(verbose.blas_errors, SciMLLogging.Silent) ||
253+
!isa(verbose.blas_invalid_args, SciMLLogging.Silent)
254+
op_info = get_blas_operation_info(:dgetrf, A, cache.b, condition = !isa(verbose.condition_number, SciMLLogging.Silent))
255+
@SciMLMessage(cache.verbose, :condition_number) do
256+
if op_info[:condition_number] === nothing
257+
return "Matrix condition number calculation failed."
258+
else
259+
return "Matrix condition number: $(round(op_info[:condition_number], sigdigits=4)) for $(size(A, 1))×$(size(A, 2)) matrix in dgetrf"
260+
end
261+
end
262+
verb_option, message = blas_info_msg(
263+
:dgetrf, info_value; extra_context = op_info)
264+
@SciMLMessage(message, verbose, verb_option)
265+
end
266+
else
267+
@SciMLMessage(cache.verbose, :blas_success) do
268+
op_info = get_blas_operation_info(:dgetrf, A, cache.b,
269+
condition = !isa(verbose.condition_number, SciMLLogging.Silent))
270+
@SciMLMessage(cache.verbose, :condition_number) do
271+
if op_info[:condition_number] === nothing
272+
return "Matrix condition number calculation failed."
273+
else
274+
return "Matrix condition number: $(round(op_info[:condition_number], sigdigits=4)) for $(size(A, 1))×$(size(A, 2)) matrix in dgetrf"
275+
end
276+
end
277+
return "BLAS LU factorization (dgetrf) completed successfully for $(op_info[:matrix_size]) matrix"
278+
end
279+
end
280+
248281
if !LinearAlgebra.issuccess(fact[1])
249282
return SciMLBase.build_linear_solution(
250283
alg, cache.u, nothing, cache; retcode = ReturnCode.Failure)

src/openblas.jl

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,12 +264,45 @@ function SciMLBase.solve!(cache::LinearCache, alg::OpenBLASLUFactorization;
264264
error("Error, OpenBLAS binary is missing but solve is being called. Report this issue")
265265
A = cache.A
266266
A = convert(AbstractMatrix, A)
267+
verbose = cache.verbose
267268
if cache.isfresh
268269
cacheval = @get_cacheval(cache, :OpenBLASLUFactorization)
269270
res = openblas_getrf!(A; ipiv = cacheval[1].ipiv, info = cacheval[2])
270271
fact = LU(res[1:3]...), res[4]
271272
cache.cacheval = fact
272273

274+
info_value = res[3]
275+
276+
if info_value != 0
277+
if !isa(verbose.blas_info, SciMLLogging.Silent) || !isa(verbose.blas_errors, SciMLLogging.Silent) ||
278+
!isa(verbose.blas_invalid_args, SciMLLogging.Silent)
279+
op_info = get_blas_operation_info(:dgetrf, A, cache.b, condition = !isa(verbose.condition_number, SciMLLogging.Silent))
280+
@SciMLMessage(cache.verbose, :condition_number) do
281+
if op_info[:condition_number] === nothing
282+
return "Matrix condition number calculation failed."
283+
else
284+
return "Matrix condition number: $(round(op_info[:condition_number], sigdigits=4)) for $(size(A, 1))×$(size(A, 2)) matrix in dgetrf"
285+
end
286+
end
287+
verb_option, message = blas_info_msg(
288+
:dgetrf, info_value; extra_context = op_info)
289+
@SciMLMessage(message, verbose, verb_option)
290+
end
291+
else
292+
@SciMLMessage(cache.verbose, :blas_success) do
293+
op_info = get_blas_operation_info(:dgetrf, A, cache.b,
294+
condition = !isa(verbose.condition_number, SciMLLogging.Silent))
295+
@SciMLMessage(cache.verbose, :condition_number) do
296+
if op_info[:condition_number] === nothing
297+
return "Matrix condition number calculation failed."
298+
else
299+
return "Matrix condition number: $(round(op_info[:condition_number], sigdigits=4)) for $(size(A, 1))×$(size(A, 2)) matrix in dgetrf"
300+
end
301+
end
302+
return "BLAS LU factorization (dgetrf) completed successfully for $(op_info[:matrix_size]) matrix"
303+
end
304+
end
305+
273306
if !LinearAlgebra.issuccess(fact[1])
274307
return SciMLBase.build_linear_solution(
275308
alg, cache.u, nothing, cache; retcode = ReturnCode.Failure)

test/verbosity.jl

Lines changed: 217 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ end
323323
@testset "BLIS Verbosity Integration Tests" begin
324324
@testset "BLIS solver with verbosity logging" begin
325325
# Test basic BLIS solver functionality with verbosity
326-
if Base.get_extension(LinearSolve, :LinearSolveBLISExt) == nothing
326+
if Base.get_extension(LinearSolve, :LinearSolveBLISExt) === nothing
327327
# Only test if BLIS is available
328328
@info "Skipping BLIS tests - BLIS not available"
329329
else
@@ -387,4 +387,220 @@ end
387387
prob_good, BLISLUFactorization(); verbose = verbose_with_cond)
388388
end
389389
end
390+
end
391+
392+
@testset "OpenBLAS Verbosity Integration Tests" begin
393+
@testset "OpenBLAS solver with verbosity logging" begin
394+
# Test basic OpenBLAS solver functionality with verbosity
395+
try
396+
# Test successful solve with success logging enabled
397+
A_good = [2.0 1.0; 1.0 2.0]
398+
b_good = [3.0, 4.0]
399+
prob_good = LinearProblem(A_good, b_good)
400+
401+
verbose_success = LinearVerbosity(
402+
blas_success = InfoLevel(),
403+
blas_errors = Silent(),
404+
blas_info = Silent()
405+
)
406+
407+
@test_logs (:info, r"BLAS LU factorization.*completed successfully") solve(
408+
prob_good, OpenBLASLUFactorization(); verbose = verbose_success)
409+
410+
# Test singular matrix with error logging
411+
A_singular = [1.0 2.0; 2.0 4.0]
412+
b_singular = [1.0, 2.0]
413+
prob_singular = LinearProblem(A_singular, b_singular)
414+
415+
verbose_errors = LinearVerbosity(
416+
blas_errors = WarnLevel(),
417+
blas_success = Silent(),
418+
blas_info = Silent()
419+
)
420+
421+
@test_logs (:warn, r"BLAS/LAPACK.*Matrix is singular") solve(
422+
prob_singular, OpenBLASLUFactorization(); verbose = verbose_errors)
423+
424+
# Test with info logging enabled
425+
verbose_info = LinearVerbosity(
426+
blas_info = InfoLevel(),
427+
blas_errors = InfoLevel(),
428+
blas_success = Silent()
429+
)
430+
431+
@test_logs (:info, r"BLAS/LAPACK.*Matrix is singular") solve(
432+
prob_singular, OpenBLASLUFactorization(); verbose = verbose_info)
433+
434+
# Test with all BLAS logging disabled - should produce no logs
435+
verbose_silent = LinearVerbosity(
436+
blas_errors = Silent(),
437+
blas_invalid_args = Silent(),
438+
blas_info = Silent(),
439+
blas_success = Silent()
440+
)
441+
442+
@test_logs min_level=SciMLLogging.Logging.Warn solve(
443+
prob_singular, OpenBLASLUFactorization(); verbose = verbose_silent)
444+
445+
# Test condition number logging if enabled
446+
verbose_with_cond = LinearVerbosity(
447+
condition_number = InfoLevel(),
448+
blas_success = InfoLevel(),
449+
blas_errors = Silent()
450+
)
451+
452+
@test_logs (:info, r"Matrix condition number:.*for.*matrix") match_mode=:any solve(
453+
prob_good, OpenBLASLUFactorization(); verbose = verbose_with_cond)
454+
catch e
455+
if isa(e, ErrorException) && occursin("OpenBLAS binary is missing", string(e))
456+
@info "Skipping OpenBLAS tests - OpenBLAS not available"
457+
else
458+
rethrow(e)
459+
end
460+
end
461+
end
462+
end
463+
464+
@testset "AppleAccelerate Verbosity Integration Tests" begin
465+
@testset "AppleAccelerate solver with verbosity logging" begin
466+
# Test basic AppleAccelerate solver functionality with verbosity
467+
try
468+
# Test successful solve with success logging enabled
469+
A_good = [2.0 1.0; 1.0 2.0]
470+
b_good = [3.0, 4.0]
471+
prob_good = LinearProblem(A_good, b_good)
472+
473+
verbose_success = LinearVerbosity(
474+
blas_success = InfoLevel(),
475+
blas_errors = Silent(),
476+
blas_info = Silent()
477+
)
478+
479+
@test_logs (:info, r"BLAS LU factorization.*completed successfully") solve(
480+
prob_good, AppleAccelerateLUFactorization(); verbose = verbose_success)
481+
482+
# Test singular matrix with error logging
483+
A_singular = [1.0 2.0; 2.0 4.0]
484+
b_singular = [1.0, 2.0]
485+
prob_singular = LinearProblem(A_singular, b_singular)
486+
487+
verbose_errors = LinearVerbosity(
488+
blas_errors = WarnLevel(),
489+
blas_success = Silent(),
490+
blas_info = Silent()
491+
)
492+
493+
@test_logs (:warn, r"BLAS/LAPACK.*Matrix is singular") solve(
494+
prob_singular, AppleAccelerateLUFactorization(); verbose = verbose_errors)
495+
496+
# Test with info logging enabled
497+
verbose_info = LinearVerbosity(
498+
blas_info = InfoLevel(),
499+
blas_errors = InfoLevel(),
500+
blas_success = Silent()
501+
)
502+
503+
@test_logs (:info, r"BLAS/LAPACK.*Matrix is singular") solve(
504+
prob_singular, AppleAccelerateLUFactorization(); verbose = verbose_info)
505+
506+
# Test with all BLAS logging disabled - should produce no logs
507+
verbose_silent = LinearVerbosity(
508+
blas_errors = Silent(),
509+
blas_invalid_args = Silent(),
510+
blas_info = Silent(),
511+
blas_success = Silent()
512+
)
513+
514+
@test_logs min_level=SciMLLogging.Logging.Warn solve(
515+
prob_singular, AppleAccelerateLUFactorization(); verbose = verbose_silent)
516+
517+
# Test condition number logging if enabled
518+
verbose_with_cond = LinearVerbosity(
519+
condition_number = InfoLevel(),
520+
blas_success = InfoLevel(),
521+
blas_errors = Silent()
522+
)
523+
524+
@test_logs (:info, r"Matrix condition number:.*for.*matrix") match_mode=:any solve(
525+
prob_good, AppleAccelerateLUFactorization(); verbose = verbose_with_cond)
526+
catch e
527+
if isa(e, ErrorException) && occursin("AppleAccelerate binary is missing", string(e))
528+
@info "Skipping AppleAccelerate tests - AppleAccelerate not available"
529+
else
530+
rethrow(e)
531+
end
532+
end
533+
end
534+
end
535+
536+
@testset "MKL Verbosity Integration Tests" begin
537+
@testset "MKL solver with verbosity logging" begin
538+
# Test basic MKL solver functionality with verbosity
539+
try
540+
# Test successful solve with success logging enabled
541+
A_good = [2.0 1.0; 1.0 2.0]
542+
b_good = [3.0, 4.0]
543+
prob_good = LinearProblem(A_good, b_good)
544+
545+
verbose_success = LinearVerbosity(
546+
blas_success = InfoLevel(),
547+
blas_errors = Silent(),
548+
blas_info = Silent()
549+
)
550+
551+
@test_logs (:info, r"BLAS LU factorization.*completed successfully") solve(
552+
prob_good, MKLLUFactorization(); verbose = verbose_success)
553+
554+
# Test singular matrix with error logging
555+
A_singular = [1.0 2.0; 2.0 4.0]
556+
b_singular = [1.0, 2.0]
557+
prob_singular = LinearProblem(A_singular, b_singular)
558+
559+
verbose_errors = LinearVerbosity(
560+
blas_errors = WarnLevel(),
561+
blas_success = Silent(),
562+
blas_info = Silent()
563+
)
564+
565+
@test_logs (:warn, r"BLAS/LAPACK.*Matrix is singular") solve(
566+
prob_singular, MKLLUFactorization(); verbose = verbose_errors)
567+
568+
# Test with info logging enabled
569+
verbose_info = LinearVerbosity(
570+
blas_info = InfoLevel(),
571+
blas_errors = InfoLevel(),
572+
blas_success = Silent()
573+
)
574+
575+
@test_logs (:info, r"BLAS/LAPACK.*Matrix is singular") solve(
576+
prob_singular, MKLLUFactorization(); verbose = verbose_info)
577+
578+
# Test with all BLAS logging disabled - should produce no logs
579+
verbose_silent = LinearVerbosity(
580+
blas_errors = Silent(),
581+
blas_invalid_args = Silent(),
582+
blas_info = Silent(),
583+
blas_success = Silent()
584+
)
585+
586+
@test_logs min_level=SciMLLogging.Logging.Warn solve(
587+
prob_singular, MKLLUFactorization(); verbose = verbose_silent)
588+
589+
# Test condition number logging if enabled
590+
verbose_with_cond = LinearVerbosity(
591+
condition_number = InfoLevel(),
592+
blas_success = InfoLevel(),
593+
blas_errors = Silent()
594+
)
595+
596+
@test_logs (:info, r"Matrix condition number:.*for.*matrix") match_mode=:any solve(
597+
prob_good, MKLLUFactorization(); verbose = verbose_with_cond)
598+
catch e
599+
if isa(e, ErrorException) && occursin("MKL binary is missing", string(e))
600+
@info "Skipping MKL tests - MKL not available"
601+
else
602+
rethrow(e)
603+
end
604+
end
605+
end
390606
end

0 commit comments

Comments
 (0)