11using LinearAlgebra
22using SparseArrays
3+ using CUDA
34using BenchmarkTools
5+ using OrderedCollections
6+ using Plots
7+
8+ println (" CPU benchmark with error-vs-time plot:\n " )
49
510include (" solver.jl" )
611
7- println (" Simple CPU benchmark:\n " )
8- A = sprand (10000 , 10000 , 0.1 )
9- b = rand (10000 )
10- display (@benchmark $ A \ $ b seconds= 20 )
11- display (@benchmark proposed_fn ($ A, $ b) seconds= 10 )
12- x1 = A \ b
13- e1 = norm (A * x1 - b)
14- x2 = proposed_fn (A, b)
15- e2 = norm (A * x2 - b)
16- println (" Error of default solver: $e1 " )
17- println (" Error of generated solver: $e2 " )
12+ # Configuration
13+ N = 15_000
14+ sparsity_levels = [0.1 , 0.5 , 0.9 ]
15+ solvers = OrderedDict (
16+ " Default" => (A, b) -> (A \ b),
17+ " Generated" => (A, b) -> proposed_fn (A, b)
18+ )
19+
20+ # Store results for plotting
21+ results = Dict ()
22+
23+ for sparsity in sparsity_levels
24+ println (" \n === Sparsity: $sparsity ===" )
25+
26+ # Generate problem
27+ A = sprand (N, N, sparsity)
28+ b = rand (N)
29+
30+ results[sparsity] = Dict ()
31+
32+ for (solver_name, solver_fn) in solvers
33+ println (" $solver_name ..." )
34+
35+ # Warm-up
36+ b_warm = copy (b)
37+ try
38+ x_warm = solver_fn (A, b_warm)
39+ catch e
40+ println (" Warning: solver failed during warm-up: $e " )
41+ continue
42+ end
43+
44+ # Benchmark
45+ b_bench = copy (b)
46+ try
47+ bench = @benchmark begin
48+ x = $ (solver_fn)($ A, $ b_bench)
49+ end seconds = 5 samples = 10
50+
51+ time_ms = median (bench. times) / 1e9 # Convert to s
52+
53+ # Compute error
54+ b_err = copy (b)
55+ x_sol = solver_fn (A, b_err)
56+ error = norm (A* x_sol - b_err) / norm (b_err)
57+
58+ results[sparsity][solver_name] = (time= time_ms, error= error)
59+ println (" Time: $(round (time_ms, digits= 3 )) ms, Error: $(round (error, sigdigits= 3 )) " )
60+ catch e
61+ println (" Error during benchmark: $e " )
62+ end
63+ end
64+ end
65+
66+ # Create error-vs-time plot
67+ p = plot (
68+ size= (800 , 800 ),
69+ # legend=:topright,
70+ legend= :bottomright ,
71+ xlabel= " Time (s)" ,
72+ ylabel= " Relative residual: ||Ax - b||₂ / ||b||₂" ,
73+ # xscale=:log10,
74+ yscale= :log10 ,
75+ guidefontsize= 22 ,# 18,
76+ tickfontsize= 20 , # 16,
77+ legendfontsize= 18 , # 14,
78+ margin= 5 * Plots. mm,
79+ framestyle= :box ,
80+ title= " Random Matrices of Size $(N) x$(N) ,\n Varying Sparsity Levels (ρ) and\n CPU Solvers" ,
81+ titlefontsize= 22 ,
82+ )
83+
84+ # Symbols encode sparsity levels; colors encode solvers.
85+ # Define marker for each sparsity and a color for each solver.
86+ # # Sparsity shapes
87+ marker_map_sparsity = OrderedDict (0.1 => :circle , 0.5 => :square , 0.9 => :utriangle )
88+ # # Solver color shades
89+ color_map_solver = OrderedDict (" Default" => :red , " Generated" => :green )
90+
91+ # Plot each point individually so marker shape shows sparsity and color shows solver.
92+ for solver_name in keys (solvers)
93+ for sparsity in sparsity_levels
94+ if sparsity in keys (results) && solver_name in keys (results[sparsity])
95+ t = results[sparsity][solver_name]. time
96+ e = results[sparsity][solver_name]. error
97+ scatter! (p, [t], [e];
98+ label= " " ,
99+ marker= marker_map_sparsity[sparsity],
100+ markersize= 15 ,
101+ color= color_map_solver[solver_name],
102+ markerstrokecolor= :black ,
103+ markerstrokewidth= 0.0 ,# 0.8,
104+ alpha= 0.45 )
105+ end
106+ end
107+ end
108+
109+ # Create a combined legend
110+ for solver_name in keys (solvers)
111+ for s in sparsity_levels
112+ lbl = " $(solver_name) , ρ:$(s) "
113+ scatter! (p, [NaN ], [NaN ]; label= lbl,
114+ marker= marker_map_sparsity[s],
115+ markersize= 15 ,
116+ color= color_map_solver[solver_name],
117+ markerstrokecolor= :black ,
118+ markerstrokewidth= 0.0 ,
119+ alpha= 0.45 )
120+ end
121+ end
122+
123+ savefig (p, " error_vs_time.pdf" )
124+ println (" \n ✓ Plot saved as error_vs_time.pdf" )
125+
126+ display (p)
0 commit comments