Commit 529cb2c8 authored by Jakub Klemsa's avatar Jakub Klemsa
Browse files

Experimental: result processing in batch.

parent 549c0210
#!/usr/bin/env ruby
require "yaml"
require "fileutils"
require_relative "./est-lambda.rb"
PLOT_WIDTH_PER_PARAMS = 130
#~ # usage
#~ USAGE = "(i) Usage: $ #{File.basename(__FILE__)} <lambda> <pi> <2^2Delta> <mode: n|m (numerical | manual)>"
#~ puts USAGE or exit if ARGV[3].nil?
#~ # read parameters
#~ LAMBDA = ARGV[0].to_i
#~ PI = ARGV[1].to_i
#~ QW = ARGV[2].to_i
#~ MODE = ARGV[3].to_sym
#~ LAMBDAs = [80, 128]
#~ PIs = [2, 3, 4, 5, 6, 7]
#~ QWs = [5]
LAMBDAs = [80]
PIs = [2, 3, 4]
QWs = [2, 3]
# output dirs & files
OUT_DIR = "out_batch"
RES_BASENAME = "batch-results"
fname_dat = RES_BASENAME + ".dat"
path_dat = File.join OUT_DIR, fname_dat
fname_png = RES_BASENAME + ".png"
fname_tex = RES_BASENAME + ".tex"
path_png = File.join OUT_DIR, fname_png
path_tex = File.join OUT_DIR, fname_tex
# prepare worst time
worst_time = 0
# read yaml & write into dat file
FileUtils.mkdir_p OUT_DIR
File.open(path_dat, 'w') do |file|
file.write "# t_med t_min N γ l n κ t logABK logAKS est. λ |BK| t_br_med |KSK| t_ks_med η_m η_C η_f V_0-cr λ π 2^2Δ\n"
file.write "# --------------------------------------------------------------------------------------------------------------------------------------------------------------------------\n"
QWs.each do |qw|
PIs.each do |pi|
LAMBDAs.each do |lambda|
# paths to files
fname_base = "batch-results__lambda-#{lambda}_pi-#{pi}_qw-#{qw}"
res_dir = "results-noises_numerical"
fname_yaml = fname_base + ".yaml"
path_yaml = File.join "..", "..", res_dir, fname_yaml
# check yaml file
$stderr.puts "(!) File '#{path_yaml}' does not exist." or exit unless File.file? path_yaml
# load results
results = YAML.load(File.read path_yaml)
$stderr.puts "(!) Results in '#{path_yaml}' are empty." or exit if results.empty?
# calc total BS median & min time
results.each{|ri| ri[:bench][:time][:time_median_ms] = ri[:bench][:time][:br_time_median_ms] + ri[:bench][:time][:ks_time_median_ms] }
results.each{|ri| ri[:bench][:time][:time_min_ms] = ri[:bench][:time][:br_time_min_ms] + ri[:bench][:time][:ks_time_min_ms] }
# calc eta_concrete
results.each{|ri| ri[:bench][:noise][:eta_concrete] = 300 * Math::sqrt(ri[:params][:_2Delta] * ri[:bench][:noise][:calc_V_0_concrete] + (ri[:params][:n] + 1).to_f / (48 * ri[:params][:N]**2)) * (1 << (ri[:params][:pi] + 1))}
# find the best median time with eta_C under 100%
bp = results.select{|ri| ri[:bench][:noise][:eta_concrete] <= 100.0 }.sort_by{|ri| ri[:bench][:time][:time_median_ms] }.first
params = bp[:params]
n_runs = bp[:bench][:n_runs]
times = bp[:bench][:time]
key_sz = bp[:bench][:key_size]
noises = bp[:bench][:noise]
lambda_LWE = est_lambda(params[:n], params[:logAKSn])
lambda_RLWE = est_lambda(params[:N], params[:logABKnn])
br_fct = times[:br_time_min_ms] / key_sz[:bsk_size] * 1000000
ks_fct = times[:ks_time_min_ms] / key_sz[:ksk_size] * 1000000
puts "(i) \e[32mBR factor: %5.2f (N = %4d, l = %2d)\n KS factor: %5.2f\e[0m" % [br_fct, params[:N], params[:l], ks_fct]
calc_V_round = (params[:n] + 1).to_f / (48 * params[:N]**2)
eta_meas = 300 * Math::sqrt(params[:_2Delta] * noises[:meas_V_0] + calc_V_round) * (1 << (params[:pi] + 1))
eta_concrete = 300 * Math::sqrt(params[:_2Delta] * noises[:calc_V_0_concrete] + calc_V_round) * (1 << (params[:pi] + 1))
eta_formula = 300 * Math::sqrt(params[:_2Delta] * noises[:calc_V_0_formula] + calc_V_round) * (1 << (params[:pi] + 1))
file.write " %7.2f %7.2f %7d %3d %3d %7d %3d %3d %7d %7d %7.2f" % [times[:time_median_ms], times[:time_min_ms], params[:N], params[:gamma], params[:l], params[:n], params[:kappa], params[:t], params[:logABKnn], params[:logAKSn], [lambda_LWE, lambda_RLWE].min]
file.write " %11d %11.2f %11d %11.2f %7.1f %7.1f %7.1f %7.3f" % [key_sz[:bsk_size], times[:br_time_median_ms], key_sz[:ksk_size], times[:ks_time_median_ms], eta_meas, eta_concrete, eta_formula, params[:v0_corr]]
file.write " %3d %3d %7d\n" % [lambda, pi, qw]
worst_time = times[:time_median_ms] > worst_time ? times[:time_median_ms] : worst_time
end
end
# separate qw's with two newlines (new dataset in gnuplot)
file.write "\n\n"
end
end
puts "(i) Results written to '#{path_dat}'."
# run gnuplot script
plot_width = PLOT_WIDTH_PER_PARAMS * (PIs.size + 2)
y_tics = worst_time > 100 ? 5 : 2
#TODO read n_runs
#TODO multi-lambda support
system "gnuplot -c plot.sh #{path_dat} #{path_png} #{plot_width} #{-1} #{y_tics} #{QWs.size}"
# system "gnuplot -c plot-tex.sh #{path_dat} #{path_tex} #{plot_width} #{results.first[:bench][:n_runs]} #{y_tics}"
puts "(i) Find plot in '#{path_png}'."
......@@ -8,6 +8,7 @@ OUT = ARG2
WID = ARG3
NRUNS = ARG4
YTICS = ARG5
QWS = ARG6
#~ RES = 'sample.dat'
#~ OUT = 'sample.png'
#~ WID = 1800
......@@ -67,6 +68,8 @@ set term epslatex size 25.9cm,10cm color colortext standalone font 10 header \
set out OUT
set multiplot layout QWS, 1
set xtics font ",8" right offset 6,-6
set x2tics font ",8"
set mytics 2
......@@ -82,6 +85,7 @@ set boxwidth 0.8
set xrange [-.5:6.5]
set yrange [0:]
#TODO resolve for multiplot
set tmargin at screen 0.46
set bmargin at screen 0.94
set lmargin at screen 0.03
......@@ -89,8 +93,12 @@ set rmargin at screen 0.999
#~ set bars small
# x(row):y(t_med):err(t_med-t_min):width(l):lc:xtic
plot RES u 0:1:($1-$2):($5/MAX_L):($3==512?3:($3==1024?2:($3==2048?5:4))):xtic('\Longstack[r]{$N = '.stringcolumn(3).', \gamma = '.stringcolumn(4).'$\\$n = '.stringcolumn(6).', l = '.stringcolumn(5).'$\\$\kappa = '.stringcolumn(7).', t = '.stringcolumn(8).'$\\$\log(BK) = '.stringcolumn(9).'$\\$\log(KS) = '.stringcolumn(10).'$\\$\lambda \approx '.stringcolumn(11).'$\\$\eta_m = '.stringcolumn(16).'\%$\\$\eta_C = '.stringcolumn(17).'\%$\\$\eta_f = '.stringcolumn(18).'\%$\\$V_{0\text{-corr}} = '.stringcolumn(19).'$}'):x2tic('$'.stringcolumn(1).'$\,ms') w boxerrorbars lc variable, \
'' u ($0):($15):($5/MAX_L/2):(0) w xerr pointtype 0 lc variable, \
'' u ($0+$5/MAX_L/2+RATIO_WID/2):($12*bs_ratio($5)+$14*KS_RATIO):(RATIO_WID):(6) w boxes lc variable, \
'' u ($0+$5/MAX_L/2+RATIO_WID/2):($14*KS_RATIO):(RATIO_WID):(4) w boxes lc variable
# x(row):y(t_med):err(t_med-t_min):width(l):lc:xtic
do for [qwi=0:QWS-1] {
plot RES index qwi u 0:1:($1-$2):($5/MAX_L):($3==512?3:($3==1024?2:($3==2048?5:4))):xtic('\Longstack[r]{$N = '.stringcolumn(3).', \gamma = '.stringcolumn(4).'$\\$n = '.stringcolumn(6).', l = '.stringcolumn(5).'$\\$\kappa = '.stringcolumn(7).', t = '.stringcolumn(8).'$\\$\log(BK) = '.stringcolumn(9).'$\\$\log(KS) = '.stringcolumn(10).'$\\$\lambda \approx '.stringcolumn(11).'$\\$\eta_m = '.stringcolumn(16).'\%$\\$\eta_C = '.stringcolumn(17).'\%$\\$\eta_f = '.stringcolumn(18).'\%$\\$V_{0\text{-corr}} = '.stringcolumn(19).'$}'):x2tic('$'.stringcolumn(1).'$\,ms') w boxerrorbars lc variable, \
'' u ($0):($15):($5/MAX_L/2):(0) w xerr pointtype 0 lc variable, \
'' u ($0+$5/MAX_L/2+RATIO_WID/2):($12*bs_ratio($5)+$14*KS_RATIO):(RATIO_WID):(6) w boxes lc variable, \
'' u ($0+$5/MAX_L/2+RATIO_WID/2):($14*KS_RATIO):(RATIO_WID):(4) w boxes lc variable
}
unset multiplot
......@@ -8,6 +8,7 @@ OUT = ARG2
WID = ARG3
NRUNS = ARG4
YTICS = ARG5
QWS = ARG6
#~ RES = 'sample.dat'
#~ OUT = 'sample.png'
#~ WID = 1800
......@@ -64,6 +65,8 @@ MAX_L = 16
set term pngcairo dashed size WID,900
set out OUT
set multiplot layout QWS, 1
set xtics font ",10" rotate by 10 right right offset 8,-.5
set x2tics font ",10"
set ytics YTICS font ",10"
......@@ -78,6 +81,7 @@ set boxwidth 0.8
#~ set xrange [-.5:]
set yrange [0:]
#TODO resolve for multiplot
set tmargin at screen 0.23
set bmargin at screen 0.92
......@@ -85,8 +89,12 @@ set bmargin at screen 0.92
set title "# of runs = ".NRUNS
# x(row):y(t_med):err(t_med-t_min):width(l):lc:xtic
plot RES u 0:1:($1-$2):($5/MAX_L):($3==512?3:($3==1024?2:($3==2048?5:4))):xtic("N = ".stringcolumn(3).", γ = ".stringcolumn(4)."\nn = ".stringcolumn(6).", l = ".stringcolumn(5)."\nκ = ".stringcolumn(7).", t = ".stringcolumn(8)."\nlog(BK) = ".stringcolumn(9)."\nlog(KS) = ".stringcolumn(10)."\nλ ≈ ".stringcolumn(11)."\nη m = ".stringcolumn(16)."%\nη C = ".stringcolumn(17)."%\nη f = ".stringcolumn(18)."%\nV0-c = ".stringcolumn(19)):x2tic(stringcolumn(1)." ms") w boxerrorbars lc variable, \
'' u ($0):($15):($5/MAX_L/2):(0) w xerr pointtype 0 lc variable, \
'' u ($0+$5/MAX_L/2+RATIO_WID/2):($12*bs_ratio($5)+$14*KS_RATIO):(RATIO_WID):(6) w boxes lc variable, \
'' u ($0+$5/MAX_L/2+RATIO_WID/2):($14*KS_RATIO):(RATIO_WID):(4) w boxes lc variable
# x(row):y(t_med):err(t_med-t_min):width(l):lc:xtic
do for [qwi=0:QWS-1] {
plot RES index qwi u 0:1:($1-$2):($5/MAX_L):($3==512?3:($3==1024?2:($3==2048?5:4))):xtic("N = ".stringcolumn(3).", γ = ".stringcolumn(4)."\nn = ".stringcolumn(6).", l = ".stringcolumn(5)."\nκ = ".stringcolumn(7).", t = ".stringcolumn(8)."\nlog(BK) = ".stringcolumn(9)."\nlog(KS) = ".stringcolumn(10)."\nλ ≈ ".stringcolumn(11)."\nη m = ".stringcolumn(16)."%\nη C = ".stringcolumn(17)."%\nη f = ".stringcolumn(18)."%\nV0-c = ".stringcolumn(19)):x2tic(stringcolumn(1)." ms") w boxerrorbars lc variable, \
'' u ($0):($15):($5/MAX_L/2):(0) w xerr pointtype 0 lc variable, \
'' u ($0+$5/MAX_L/2+RATIO_WID/2):($12*bs_ratio($5)+$14*KS_RATIO):(RATIO_WID):(6) w boxes lc variable, \
'' u ($0+$5/MAX_L/2+RATIO_WID/2):($14*KS_RATIO):(RATIO_WID):(4) w boxes lc variable
}
unset multiplot
......@@ -95,6 +95,7 @@ puts "(i) Results written to '#{path_dat}'."
# run gnuplot script
plot_width = PLOT_WIDTH_PER_PARAMS * (results.size + 2)
y_tics = worst_time > 100 ? 5 : 2
system "gnuplot -c plot.sh #{path_dat} #{path_png} #{plot_width} #{results.first[:bench][:n_runs]} #{y_tics}"
N_DATA_SETS = 1 # only used for batch mode
system "gnuplot -c plot.sh #{path_dat} #{path_png} #{plot_width} #{results.first[:bench][:n_runs]} #{y_tics} #{N_DATA_SETS}"
#~ system "gnuplot -c plot-tex.sh #{path_dat} #{path_tex} #{plot_width} #{results.first[:bench][:n_runs]} #{y_tics}"
puts "(i) Find plot in '#{path_png}'."
......@@ -84,17 +84,7 @@ fn main() -> Result<(), Box<dyn Error>> {
if Path::new(&nss_filename).exists() { fs::remove_file(&nss_filename)?; }
nss_file = File::create(&nss_filename).expect("File::create noises failed.");
// (A) bench all generated/provided parameters
#[cfg(feature = "manual")]
for (par_i, par) in par_grp.iter().enumerate() {
println!("{}", format!("\n(i) {} variant {}/{} in group {}/{}\n",
task_str, par_i+1, par_grp.len(), par_gi+1, all_pars.len(),
).purple());
println!("{:?}\n", par);
par.bench_p(&stp, &mut res_file, &mut nss_file)?;
}
// (B) sort by numeric estimate & bench the best ones
// (A) bench numerically generated parameters
#[cfg(feature = "numerical")]
for (par_i, par) in par_grp.iter().enumerate() { // .take(N_TOP_NUM_BENCH)
println!("{}", format!("\n(i) {} variant {}/{} in group {}/{}\n",
......@@ -110,6 +100,16 @@ fn main() -> Result<(), Box<dyn Error>> {
//~ eprintln!("(!) Minimum search by numerically estimated BS time failed.\n");
//~ }
// (B) bench manually provided parameters
#[cfg(feature = "manual")]
for (par_i, par) in par_grp.iter().enumerate() {
println!("{}", format!("\n(i) {} variant {}/{} in group {}/{}\n",
task_str, par_i+1, par_grp.len(), par_gi+1, all_pars.len(),
).purple());
println!("{:?}\n", par);
par.bench_p(&stp, &mut res_file, &mut nss_file)?;
}
println!("{}", format!("\n(i) {} finished for {}-bit params with π = {}, 2^2∆ = {}\n Results written to '{}'.\n Noises written to '{}'.\n\n ============================================================================\n",
task_str, lambda, pi, qw, res_filename, nss_filename,
).bold().blue());
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment