FGCS/eval_timings.jl
2025-03-14 11:35:21 +01:00

292 lines
8.0 KiB
Julia

using DataFrames, RCall, Statistics, Plots, Base.Threads, CSV, CategoricalArrays
prefix = "barite_fgcs"
input_dir = "barite/"
timing_file = "timings.qs2"
ema_file = "ema.out.csv"
relevant_timings = ["Chemistry", "Phreeqc", "PHT_read", "PHT_write", "DHT_gather", "Interpolation", "Energy"]
grid_size = 400 * 400
iterations = 5000
calculations = grid_size * iterations
output_dir = "timings"
if !isdir(output_dir)
mkdir(output_dir)
end
function read_timings(timing_file)
res = nothing
@rput timing_file
R"res <- qs2::qs_read(timing_file)"
@rget res
return res
end
function read_ema(ema_file)
if (!isfile(ema_file))
return DataFrame()
end
return CSV.read(ema_file, DataFrame)
end
function eval_timings_interp(timings)
chemistry = timings[:chemistry]
time_vec = [chemistry[:simtime],
sum(chemistry[:phreeqc_time]),
sum(chemistry[:interp_w]),
sum(chemistry[:interp_r]),
sum(chemistry[:interp_g]),
sum(chemistry[:interp_fc])]
interp_df = DataFrame(Calls=chemistry[:interp_calls],
Cached=chemistry[:interp_cached])
return time_vec, interp_df
end
function eval_ema(ema_df)
if (nrow(ema_df) == 0)
return 0.0
end
only_package = filter(row -> occursin(r"package-\d+", row[:device_name]), ema_df)
return sum(only_package[!, :energy]) * 1e-6 * (1 / 3600)
end
function eval_timings_ref(timings)
chemistry = timings[:chemistry]
time_vec = [chemistry[:simtime],
sum(chemistry[:phreeqc_time]),
0, 0, 0, 0]
return time_vec
end
function find_all_directories(input_dir, prefix)
result_dirs = readdir(input_dir, join=true)
result_dirs = filter(x -> occursin(prefix, x), result_dirs)
return result_dirs
end
function workhorse_loop(dirs)
df_timings = DataFrame()
df_interp = Dict{Tuple{Int,Int},DataFrame}()
for dir in dirs
metainfo = split(basename(dir), "_")
type = nothing
aqueous = 0
minerals = 0
energy = eval_ema(read_ema(joinpath(dir, ema_file)))
if (metainfo[3] == "ref")
type = "Reference"
timings = read_timings(joinpath(dir, timing_file))
time_vec = eval_timings_ref(timings)
else
aqueous = parse(Int, metainfo[3])
minerals = parse(Int, metainfo[4])
type = "(" * string(aqueous) * "," * string(minerals) * ")"
timings = read_timings(joinpath(dir, timing_file))
time_vec, interp_df = eval_timings_interp(timings)
df_interp[(aqueous, minerals)] = interp_df
end
push!(time_vec, energy)
new_df = DataFrame(relevant_timings .=> time_vec)
local_df = DataFrame(Type=type, Aqueous=aqueous, Minerals=minerals)
local_df = hcat(local_df, new_df)
append!(df_timings, local_df)
end
return df_timings, df_interp
end
function eval_additional_info(df, interp_dict, grid_size, iterations)
interp_full = Vector()
for row in eachrow(df)
if (row[:Type] != "Reference")
interp_count = sum(interp_dict[(row[:Aqueous], row[:Minerals])][!, :Calls])
push!(interp_full, interp_count)
else
push!(interp_full, 0)
end
end
calculations = grid_size * iterations
phreeqc_calls = calculations .- interp_full
time_per_phreeqc = (df[!, :Phreeqc] ./ phreeqc_calls)
df = hcat(df, DataFrame(Phreeqc_calls=phreeqc_calls, Time_per_Phreeqc=time_per_phreeqc, Interp_calls=interp_full))
return df
end
function color_from_aqueous!(df)
my_colors = palette(:viridis, 4)
df[!, :Type] = CategoricalArray(df[!, :Type])
color_vec = Vector()
for row in eachrow(df)
if (row[:Type] == "Reference")
push!(color_vec, my_colors[1])
else
push!(color_vec, my_colors[row[:Aqueous]])
end
end
df[!, :Colors] = color_vec
end
dirs = find_all_directories("barite/", "barite_fgcs")
df_timings, df_interp = workhorse_loop(dirs)
group = groupby(df_timings, [:Type, :Aqueous, :Minerals])
combine_df = combine(group,
relevant_timings .=> mean .=> relevant_timings,
)
df_timings = eval_additional_info(combine_df, df_interp, grid_size, iterations)
CSV.write("$output_dir/timings_barite.csv", df_timings)
for (key, value) in df_interp
CSV.write("$output_dir/interp_barite_$(key[1])_$(key[2]).csv", value)
end
color_from_aqueous!(df_timings)
# plot with different colors and shapes in bars
bar(df_timings[!, :Type],
df_timings[!, :Chemistry],
color=df_timings[!, :Colors],
xguidefontsize=8,
yguidefontsize=8,
xtickfontsize=6,
ytickfontsize=6,
legend=false,
ylabel="Time [s]",
xlabel="Simulation Type",
formatter=:plain,
yminorgrid=true,
ylimits=(0, 60000))
savefig("$output_dir/timings_barite.pdf")
function get_count_of_id2(initqsfile)
res = nothing
@rput initqsfile
R"res <- qs2::qs_read(initqsfile)"
@rget res
id = res[!, :ID]
return count(x -> x == 2.0, id)
end
bar(df_timings[!, :Type], df_timings[!, :Energy],
color=df_timings[!, :Colors],
xguidefontsize=8,
yguidefontsize=8,
xtickfontsize=6,
ytickfontsize=6,
legend=false,
formatter=:plain,
yminorgrid=true,
ylimits=(0, 12000),
yticks=[0, 2000, 4000, 6000, 8000, 10000, 12000],
yminorticks=4,
ylabel="Energy [Wh]", xlabel="Simulation Type")
savefig("$output_dir/energy_barite.pdf")
max_count = get_count_of_id2("barite/barite_fgcs_ref_128_3/iter_0000.qs2")
interp_3_1 = df_interp[(3, 1)]
plot(interp_3_1[!, :Calls],
color=:black,
xguidefontsize=8,
yguidefontsize=8,
xtickfontsize=6,
ytickfontsize=6,
legend=false,
ylimits=(68000, 82000),
yminorgrid=true,
yminorticks=4,
formatter=:plain,
ylabel="Interpolation Calls",
xlabel="Iteration")
hline!([max_count],
color=:red,
linestyle=:dash,
label="Mean")
savefig("$output_dir/interp_calls_3_1_clipped.pdf")
prefix = "dolo_inter"
input_dir = "dolomite/"
dirs = find_all_directories("dolomite/", "dolo_inter")
df_timings, df_interp = workhorse_loop(dirs)
group = groupby(df_timings, [:Type, :Aqueous, :Minerals])
combine_df = combine(group,
relevant_timings .=> mean .=> relevant_timings,
)
df_timings = eval_additional_info(combine_df, df_interp, grid_size, iterations)
CSV.write("$output_dir/timings_dolomite.csv", df_timings)
for (key, value) in df_interp
CSV.write("$output_dir/interp_dolomite_$(key[1])_$(key[2]).csv", value)
end
color_from_aqueous!(df_timings)
bar(df_timings[!, :Type], df_timings[!, :Chemistry],
color=df_timings[!, :Colors],
xguidefontsize=8,
yguidefontsize=8,
xtickfontsize=6,
ytickfontsize=6,
legend=false,
formatter=:plain,
yminorgrid=true,
ylim=(0, 15000),
yticks=0:2500:15000,
ylabel="Time [s]", xlabel="Type")
savefig("$output_dir/timings_dolomite.pdf")
bar(df_timings[!, :Type], df_timings[!, :Energy],
color=df_timings[!, :Colors],
xguidefontsize=8,
yguidefontsize=8,
xtickfontsize=6,
ytickfontsize=6,
legend=false,
formatter=:plain,
yminorgrid=true,
ylim=(0, 3000),
ylabel="Energy [Wh]", xlabel="Type")
savefig("$output_dir/energy_dolomite.pdf")