Beingamanforever

pdist & pdist2 benchmarking script (switch statement placement)

Jan 27th, 2026
82
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Octave 4.41 KB | None | 0 0
  1. function bench_switch ()
  2.   N_vals = [500, 1000, 2000, 3000, 4000];
  3.   P = 10;
  4.   n_runs = 5;
  5.   n_warmup = 2;
  6.  
  7.   res_pdist = zeros (numel (N_vals), 4);
  8.   res_pdist2 = zeros (numel (N_vals), 4);
  9.  
  10.   for idx = 1:numel (N_vals)
  11.     N = N_vals(idx);
  12.     rand ("seed", 12345);
  13.     X = rand (N, P);
  14.     Y = rand (N, P);
  15.  
  16.     t_inside = run_timed (@() pdist_switch_inside (X), n_runs, n_warmup);
  17.     t_outside = run_timed (@() pdist_switch_outside (X), n_runs, n_warmup);
  18.     res_pdist(idx, :) = [N, t_inside, t_outside, t_inside / t_outside];
  19.  
  20.     t_inside = run_timed (@() pdist2_switch_inside (X, Y), n_runs, n_warmup);
  21.     t_outside = run_timed (@() pdist2_switch_outside (X, Y), n_runs, n_warmup);
  22.     res_pdist2(idx, :) = [N, t_inside, t_outside, t_inside / t_outside];
  23.   endfor
  24.  
  25.   print_table ("pdist: Switch Inside vs Outside", {"N", "t_inside", "t_outside", "ratio"}, res_pdist);
  26.   print_table ("pdist2: Switch Inside vs Outside", {"N", "t_inside", "t_outside", "ratio"}, res_pdist2);
  27.  
  28.   save_csv ("bench_pdist_switch.csv", {"N", "t_inside", "t_outside", "ratio"}, res_pdist);
  29.   save_csv ("bench_pdist2_switch.csv", {"N", "t_inside", "t_outside", "ratio"}, res_pdist2);
  30.  
  31.   make_plot ("pdist_switch.png", "pdist: Switch Inside vs Outside", N_vals, ...
  32.              res_pdist(:,2), res_pdist(:,3), "Inside", "Outside");
  33.   make_plot ("pdist2_switch.png", "pdist2: Switch Inside vs Outside", N_vals, ...
  34.              res_pdist2(:,2), res_pdist2(:,3), "Inside", "Outside");
  35. endfunction
  36.  
  37. function t = run_timed (fn, n_runs, n_warmup)
  38.   for w = 1:n_warmup, fn (); endfor
  39.   times = zeros (n_runs, 1);
  40.   for r = 1:n_runs, tic; fn (); times(r) = toc; endfor
  41.   t = median (times);
  42. endfunction
  43.  
  44. function print_table (title, headers, data)
  45.   printf ("\n%s\n%s\n", title, repmat ("-", 1, 60));
  46.   printf ("%-8s %12s %12s %12s\n", headers{:});
  47.   for i = 1:rows (data)
  48.     printf ("%-8d %12.4f %12.4f %12.3fx\n", data(i,1), data(i,2), data(i,3), data(i,4));
  49.   endfor
  50.   printf ("\n");
  51. endfunction
  52.  
  53. function save_csv (fname, headers, data)
  54.   fid = fopen (fname, "w");
  55.   fprintf (fid, "%s\n", strjoin (headers, ","));
  56.   for i = 1:rows (data)
  57.     fprintf (fid, "%d,%.6f,%.6f,%.4f\n", data(i,1), data(i,2), data(i,3), data(i,4));
  58.   endfor
  59.   fclose (fid);
  60.   printf ("Saved: %s\n", fname);
  61. endfunction
  62.  
  63. function make_plot (fname, ttl, N_vals, t1, t2, leg1, leg2)
  64.   h = figure ("visible", "off");
  65.   semilogy (N_vals, t1, "ro-", "linewidth", 2, "markersize", 8);
  66.   hold on;
  67.   semilogy (N_vals, t2, "bs-", "linewidth", 2, "markersize", 8);
  68.   hold off;
  69.   xlabel ("N"); ylabel ("Time (s)"); title (ttl);
  70.   legend ({leg1, leg2}, "location", "northwest");
  71.   grid on;
  72.   print (h, fname, "-dpng", "-r150");
  73.   close (h);
  74.   printf ("Saved: %s\n", fname);
  75. endfunction
  76.  
  77. function Y = pdist_switch_inside (X)
  78.   n = rows (X);
  79.   n_pairs = n * (n - 1) / 2;
  80.   Y = zeros (1, n_pairs);
  81.   block_size = 1024;
  82.   idx = 1;
  83.   for i = 1:n-1
  84.     j_vals = (i+1):n;
  85.     n_j = numel (j_vals);
  86.     for j_start = 1:block_size:n_j
  87.       j_end = min (j_start + block_size - 1, n_j);
  88.       j_block = j_vals(j_start:j_end);
  89.       switch "euclidean"
  90.         case "euclidean"
  91.           diff_block = X(i, :) - X(j_block, :);
  92.           dists = sqrt (sum (diff_block .^ 2, 2))';
  93.       endswitch
  94.       Y(idx:idx + numel(j_block) - 1) = dists;
  95.       idx = idx + numel (j_block);
  96.     endfor
  97.   endfor
  98. endfunction
  99.  
  100. function Y = pdist_switch_outside (X)
  101.   n = rows (X);
  102.   n_pairs = n * (n - 1) / 2;
  103.   Y = zeros (1, n_pairs);
  104.   idx = 1;
  105.   for i = 1:n-1
  106.     diff_block = X(i, :) - X((i+1):n, :);
  107.     dists = sqrt (sum (diff_block .^ 2, 2))';
  108.     n_dists = numel (dists);
  109.     Y(idx:idx + n_dists - 1) = dists;
  110.     idx = idx + n_dists;
  111.   endfor
  112. endfunction
  113.  
  114. function D = pdist2_switch_inside (X, Y)
  115.   M = rows (X);
  116.   N = rows (Y);
  117.   D = zeros (M, N);
  118.   block_size = 1024;
  119.   for i_start = 1:block_size:M
  120.     i_end = min (i_start + block_size - 1, M);
  121.     block_rows = i_start:i_end;
  122.     n_block = numel (block_rows);
  123.     for bi = 1:n_block
  124.       i = block_rows(bi);
  125.       switch "euclidean"
  126.         case "euclidean"
  127.           diff_ij = X(i, :) - Y;
  128.           D(i, :) = sqrt (sum (diff_ij .^ 2, 2))';
  129.       endswitch
  130.     endfor
  131.   endfor
  132. endfunction
  133.  
  134. function D = pdist2_switch_outside (X, Y)
  135.   M = rows (X);
  136.   N = rows (Y);
  137.   D = zeros (M, N);
  138.   for i = 1:M
  139.     diff_ij = X(i, :) - Y;
  140.     D(i, :) = sqrt (sum (diff_ij .^ 2, 2))';
  141.   endfor
  142. endfunction
  143.  
Advertisement
Add Comment
Please, Sign In to add comment