diff --git a/docs/perf_tests/basic_jtest.dat b/docs/perf_tests/basic_jtest.dat new file mode 100644 index 000000000..2ab3bcd4e --- /dev/null +++ b/docs/perf_tests/basic_jtest.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 4.03 0.53 + 2 8.07 0.68 + 4 15.97 0.94 + 8 31.93 1.57 + 16 61.46 3.20 + 32 92.77 4.87 diff --git a/docs/perf_tests/basic_large.dat b/docs/perf_tests/basic_large.dat new file mode 100644 index 000000000..52a4393bf --- /dev/null +++ b/docs/perf_tests/basic_large.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 5.00 0.00 + 2 10.00 0.00 + 4 21.70 6.56 + 8 39.43 1.72 + 16 80.01 2.43 + 32 158.83 2.24 diff --git a/docs/perf_tests/basic_large_saturation.dat b/docs/perf_tests/basic_large_saturation.dat new file mode 100644 index 000000000..e3c91a8e6 --- /dev/null +++ b/docs/perf_tests/basic_large_saturation.dat @@ -0,0 +1,17 @@ +# nthreads avg_rate rms + 1 3.98 0.08 + 2 8.07 0.25 + 3 12.03 0.12 + 4 16.00 0.00 + 5 20.00 0.00 + 6 24.00 0.00 + 7 28.00 0.00 + 8 32.03 0.12 + 9 36.00 0.00 + 10 40.00 0.00 + 11 40.00 0.00 + 12 40.00 0.00 + 13 39.93 0.25 + 14 40.00 0.00 + 15 39.93 0.25 + 16 40.00 0.00 diff --git a/docs/perf_tests/basic_medium.dat b/docs/perf_tests/basic_medium.dat new file mode 100644 index 000000000..598bda9cb --- /dev/null +++ b/docs/perf_tests/basic_medium.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 49.94 0.24 + 2 100.10 0.52 + 4 199.87 0.50 + 8 400.03 3.16 + 16 797.37 1.77 + 32 1385.96 11.83 diff --git a/docs/perf_tests/basic_medium_saturation.dat b/docs/perf_tests/basic_medium_saturation.dat new file mode 100644 index 000000000..f2025fda6 --- /dev/null +++ b/docs/perf_tests/basic_medium_saturation.dat @@ -0,0 +1,17 @@ +# nthreads avg_rate rms + 1 40.01 0.03 + 2 79.93 0.25 + 3 119.93 0.25 + 4 159.90 0.37 + 5 199.83 0.35 + 6 239.90 0.27 + 7 279.87 0.34 + 8 319.70 0.44 + 9 359.73 0.44 + 10 397.67 0.79 + 11 397.23 0.75 + 12 396.83 0.85 + 13 397.30 0.57 + 14 397.30 0.44 + 15 397.27 0.77 + 16 396.63 2.13 diff --git a/docs/perf_tests/basic_mini.dat b/docs/perf_tests/basic_mini.dat new file mode 100644 index 000000000..c8a856ade --- /dev/null +++ b/docs/perf_tests/basic_mini.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 192548.67 909.47 + 2 228309.97 8005.31 + 4 157134.13 2124.88 + 8 138713.43 2024.73 + 16 125931.90 4604.27 + 32 117078.33 6739.70 diff --git a/docs/perf_tests/basic_small.dat b/docs/perf_tests/basic_small.dat new file mode 100644 index 000000000..dfc06a690 --- /dev/null +++ b/docs/perf_tests/basic_small.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 4765.23 43.28 + 2 9643.33 33.80 + 4 19230.50 116.03 + 8 38369.27 139.56 + 16 67814.23 2100.95 + 32 46497.08 3820.91 diff --git a/docs/perf_tests/basic_small_saturation.dat b/docs/perf_tests/basic_small_saturation.dat new file mode 100644 index 000000000..850c4f02e --- /dev/null +++ b/docs/perf_tests/basic_small_saturation.dat @@ -0,0 +1,17 @@ +# nthreads avg_rate rms + 1 3878.47 11.41 + 2 7766.60 5.48 + 3 11638.87 15.66 + 4 15549.30 13.82 + 5 19365.33 25.11 + 6 23227.90 32.14 + 7 27069.33 52.31 + 8 30702.44 142.87 + 9 33474.97 108.34 + 10 33224.83 64.16 + 11 32529.70 327.39 + 12 32592.27 262.56 + 13 31563.40 847.31 + 14 31986.87 367.67 + 15 31814.23 348.19 + 16 31706.07 360.37 diff --git a/docs/perf_tests/samples.dat b/docs/perf_tests/samples.dat new file mode 100644 index 000000000..d79ea9c87 --- /dev/null +++ b/docs/perf_tests/samples.dat @@ -0,0 +1,241 @@ +# nthreads rate + 1 0.28 + 1 1.00 + 1 0.00 + 1 1.00 + 1 0.00 + 1 0.00 + 1 1.00 + 1 0.00 + 1 0.00 + 1 1.00 + 1 0.00 + 1 0.00 + 1 1.00 + 1 0.00 + 1 0.00 + 2 1.50 + 2 2.00 + 2 4.00 + 2 3.00 + 2 1.00 + 2 5.00 + 2 5.00 + 2 2.00 + 2 3.00 + 2 5.00 + 2 2.00 + 2 4.00 + 2 5.00 + 2 3.00 + 2 3.00 + 3 7.00 + 3 3.00 + 3 6.00 + 3 7.00 + 3 3.00 + 3 7.00 + 3 5.00 + 3 5.00 + 3 4.00 + 3 7.00 + 3 5.00 + 3 7.00 + 3 2.00 + 3 6.00 + 3 7.00 + 4 8.00 + 4 7.00 + 4 6.00 + 4 7.00 + 4 10.00 + 4 3.00 + 4 7.00 + 4 10.00 + 4 7.00 + 4 5.00 + 4 8.00 + 4 8.00 + 4 7.00 + 4 5.00 + 4 8.00 + 5 10.00 + 5 8.00 + 5 8.00 + 5 11.00 + 5 8.00 + 5 8.00 + 5 10.00 + 5 8.00 + 5 9.00 + 5 10.00 + 5 8.00 + 5 9.00 + 5 8.00 + 5 10.00 + 5 9.00 + 6 10.50 + 6 13.00 + 6 11.00 + 6 9.00 + 6 9.00 + 6 14.00 + 6 10.00 + 6 9.00 + 6 12.00 + 6 10.00 + 6 10.00 + 6 11.00 + 6 11.00 + 6 9.00 + 6 11.00 + 7 13.50 + 7 12.00 + 7 12.00 + 7 12.00 + 7 14.00 + 7 11.00 + 7 13.00 + 7 12.00 + 7 10.00 + 7 15.00 + 7 11.00 + 7 14.00 + 7 13.00 + 7 11.00 + 7 13.00 + 8 16.00 + 8 10.00 + 8 14.00 + 8 15.00 + 8 13.00 + 8 10.00 + 8 19.00 + 8 13.00 + 8 13.00 + 8 12.00 + 8 16.00 + 8 12.00 + 8 11.00 + 8 11.00 + 8 16.00 + 9 16.50 + 9 14.00 + 9 16.00 + 9 15.00 + 9 15.00 + 9 18.00 + 9 14.00 + 9 16.00 + 9 17.00 + 9 14.00 + 9 17.00 + 9 16.00 + 9 16.00 + 9 17.00 + 9 15.00 + 10 18.50 + 10 16.00 + 10 17.00 + 10 18.00 + 10 15.00 + 10 19.00 + 10 18.00 + 10 17.00 + 10 16.00 + 10 19.00 + 10 16.00 + 10 19.00 + 10 18.00 + 10 16.00 + 10 18.00 + 11 19.50 + 11 20.00 + 11 20.00 + 11 20.00 + 11 20.00 + 11 20.00 + 11 20.00 + 11 20.00 + 11 20.00 + 11 20.00 + 11 18.00 + 11 19.00 + 11 20.00 + 11 20.00 + 11 19.00 + 12 19.00 + 12 19.00 + 12 20.00 + 12 19.98 + 12 20.00 + 12 19.00 + 12 20.00 + 12 20.00 + 12 19.00 + 12 20.00 + 12 20.00 + 12 20.00 + 12 20.00 + 12 20.00 + 12 20.00 + 13 20.00 + 13 20.00 + 13 20.00 + 13 20.00 + 13 20.00 + 13 20.00 + 13 20.00 + 13 20.00 + 13 20.00 + 13 19.00 + 13 19.00 + 13 19.00 + 13 19.00 + 13 20.00 + 13 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 14 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 20.00 + 15 18.98 + 15 20.00 + 15 20.00 + 15 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 + 16 20.00 diff --git a/docs/perf_tests/source_large.dat b/docs/perf_tests/source_large.dat new file mode 100644 index 000000000..5ac7fcf23 --- /dev/null +++ b/docs/perf_tests/source_large.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 5.00 0.00 + 2 5.00 0.00 + 4 5.00 0.00 + 8 5.00 0.00 + 16 5.00 0.00 + 32 5.00 0.00 diff --git a/docs/perf_tests/source_medium.dat b/docs/perf_tests/source_medium.dat new file mode 100644 index 000000000..74fa5dc1e --- /dev/null +++ b/docs/perf_tests/source_medium.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 99.65 0.46 + 2 99.80 0.40 + 4 99.73 0.44 + 8 99.87 0.34 + 16 99.73 0.44 + 32 99.93 0.25 diff --git a/docs/perf_tests/source_mini.dat b/docs/perf_tests/source_mini.dat new file mode 100644 index 000000000..a43c7affc --- /dev/null +++ b/docs/perf_tests/source_mini.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 571538.63 1652.21 + 2 573767.63 4950.00 + 4 570312.60 6909.59 + 8 575544.80 710.41 + 16 574226.97 4402.65 + 32 576220.87 1423.82 diff --git a/docs/perf_tests/source_small.dat b/docs/perf_tests/source_small.dat new file mode 100644 index 000000000..62dddf86d --- /dev/null +++ b/docs/perf_tests/source_small.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 19223.73 18.36 + 2 19160.77 63.97 + 4 19101.03 103.28 + 8 19138.20 26.04 + 16 19047.70 74.41 + 32 19060.43 91.53 diff --git a/docs/perf_tests/tap_chain_plot.toml b/docs/perf_tests/tap_chain_plot.toml new file mode 100644 index 000000000..f275e878c --- /dev/null +++ b/docs/perf_tests/tap_chain_plot.toml @@ -0,0 +1,23 @@ + +title = "Chain length scaling" +output_filename = "chain_length_scaling.pdf" +use_latex = true + +[[test]] +key = "1 JEventProcessor" +datafile = "tap_chain_tests_1.dat" +t_par = 1 +t_seq = 1 + +[[test]] +key = "4 JEventProcessors" +datafile = "tap_chain_tests_4.dat" +t_par = 1 +t_seq = 1 + +[[test]] +key = "16 JEventProcessors" +datafile = "tap_chain_tests_16.dat" +t_par = 1 +t_seq = 1 + diff --git a/docs/perf_tests/tapchain_16_large.dat b/docs/perf_tests/tapchain_16_large.dat new file mode 100644 index 000000000..6356d4dca --- /dev/null +++ b/docs/perf_tests/tapchain_16_large.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 5.00 0.00 + 2 10.00 0.00 + 4 20.07 0.57 + 8 40.13 0.81 + 16 79.83 5.17 + 32 158.82 1.51 diff --git a/docs/perf_tests/tapchain_16_medium.dat b/docs/perf_tests/tapchain_16_medium.dat new file mode 100644 index 000000000..6ad9b7ea3 --- /dev/null +++ b/docs/perf_tests/tapchain_16_medium.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 99.53 0.50 + 2 198.93 1.00 + 4 398.00 1.51 + 8 794.45 4.21 + 16 1573.40 11.86 + 32 1839.75 28.12 diff --git a/docs/perf_tests/tapchain_16_mini.dat b/docs/perf_tests/tapchain_16_mini.dat new file mode 100644 index 000000000..9f090ca74 --- /dev/null +++ b/docs/perf_tests/tapchain_16_mini.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 30381.97 546.07 + 2 42471.33 1310.46 + 4 42298.23 1021.10 + 8 37348.20 1409.38 + 16 27397.50 1021.15 + 32 27339.00 1120.14 diff --git a/docs/perf_tests/tapchain_16_small.dat b/docs/perf_tests/tapchain_16_small.dat new file mode 100644 index 000000000..bfa785447 --- /dev/null +++ b/docs/perf_tests/tapchain_16_small.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 4291.43 10.49 + 2 8534.51 22.30 + 4 16919.70 44.73 + 8 32322.07 369.66 + 16 25432.77 414.78 + 32 22783.20 298.34 diff --git a/docs/perf_tests/tapchain_1_large.dat b/docs/perf_tests/tapchain_1_large.dat new file mode 100644 index 000000000..0c25718a3 --- /dev/null +++ b/docs/perf_tests/tapchain_1_large.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 5.05 0.20 + 2 10.07 0.25 + 4 20.37 0.90 + 8 40.77 5.26 + 16 79.79 2.41 + 32 159.13 2.08 diff --git a/docs/perf_tests/tapchain_1_medium.dat b/docs/perf_tests/tapchain_1_medium.dat new file mode 100644 index 000000000..d8ce94d9b --- /dev/null +++ b/docs/perf_tests/tapchain_1_medium.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 99.97 0.29 + 2 199.80 0.40 + 4 401.20 4.97 + 8 798.87 2.00 + 16 1581.54 11.64 + 32 2141.22 67.64 diff --git a/docs/perf_tests/tapchain_1_mini.dat b/docs/perf_tests/tapchain_1_mini.dat new file mode 100644 index 000000000..8b3ff8ba1 --- /dev/null +++ b/docs/perf_tests/tapchain_1_mini.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 186451.30 3754.39 + 2 222209.90 14427.90 + 4 140394.80 9895.93 + 8 135044.63 3637.39 + 16 124828.17 5194.98 + 32 128929.50 2842.95 diff --git a/docs/perf_tests/tapchain_1_small.dat b/docs/perf_tests/tapchain_1_small.dat new file mode 100644 index 000000000..ce5ee23b4 --- /dev/null +++ b/docs/perf_tests/tapchain_1_small.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 4843.00 13.04 + 2 9676.78 24.87 + 4 19299.10 40.60 + 8 38288.80 157.82 + 16 65746.85 3535.38 + 32 46664.77 1872.14 diff --git a/docs/perf_tests/tapchain_4_large.dat b/docs/perf_tests/tapchain_4_large.dat new file mode 100644 index 000000000..30e9e826c --- /dev/null +++ b/docs/perf_tests/tapchain_4_large.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 5.03 0.11 + 2 10.00 0.00 + 4 20.13 0.34 + 8 40.63 3.46 + 16 80.09 3.36 + 32 158.29 1.84 diff --git a/docs/perf_tests/tapchain_4_medium.dat b/docs/perf_tests/tapchain_4_medium.dat new file mode 100644 index 000000000..d1f7ed7f8 --- /dev/null +++ b/docs/perf_tests/tapchain_4_medium.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 99.75 0.41 + 2 199.87 0.62 + 4 399.80 2.01 + 8 798.23 1.62 + 16 1589.36 6.14 + 32 1957.87 31.81 diff --git a/docs/perf_tests/tapchain_4_mini.dat b/docs/perf_tests/tapchain_4_mini.dat new file mode 100644 index 000000000..2587e7e74 --- /dev/null +++ b/docs/perf_tests/tapchain_4_mini.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 90187.40 1958.89 + 2 101823.93 2097.91 + 4 109760.03 3449.42 + 8 90616.70 4449.21 + 16 83729.63 2426.49 + 32 82653.90 3065.21 diff --git a/docs/perf_tests/tapchain_4_small.dat b/docs/perf_tests/tapchain_4_small.dat new file mode 100644 index 000000000..8d3bf2f83 --- /dev/null +++ b/docs/perf_tests/tapchain_4_small.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 4663.85 36.99 + 2 9313.53 75.28 + 4 18764.37 45.94 + 8 37350.40 105.98 + 16 60937.73 4344.56 + 32 44171.79 454.10 diff --git a/docs/perf_tests/tapchain_pipelining.dat b/docs/perf_tests/tapchain_pipelining.dat new file mode 100644 index 000000000..264627179 --- /dev/null +++ b/docs/perf_tests/tapchain_pipelining.dat @@ -0,0 +1,17 @@ +# nthreads avg_rate rms + 1 16.67 0.47 + 2 33.37 0.46 + 3 49.90 0.27 + 4 66.57 0.48 + 5 83.33 0.47 + 6 99.67 0.70 + 7 99.87 0.34 + 8 99.80 0.40 + 9 99.93 0.25 + 10 99.87 0.34 + 11 99.93 0.25 + 12 99.43 1.49 + 13 99.87 0.34 + 14 99.93 0.25 + 15 99.93 0.25 + 16 99.87 0.34 diff --git a/docs/perf_tests/unfold_large.dat b/docs/perf_tests/unfold_large.dat new file mode 100644 index 000000000..ea17820c1 --- /dev/null +++ b/docs/perf_tests/unfold_large.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 2.54 1.99 + 2 4.97 1.37 + 4 10.13 0.81 + 8 20.27 2.35 + 16 40.36 2.26 + 32 80.02 3.30 diff --git a/docs/perf_tests/unfold_large_saturation.dat b/docs/perf_tests/unfold_large_saturation.dat new file mode 100644 index 000000000..66d1f8ec9 --- /dev/null +++ b/docs/perf_tests/unfold_large_saturation.dat @@ -0,0 +1,17 @@ +# nthreads avg_rate rms + 1 0.35 0.46 + 2 3.23 1.33 + 3 5.40 1.67 + 4 7.07 1.77 + 5 8.93 1.00 + 6 10.63 1.44 + 7 12.43 1.33 + 8 13.40 2.50 + 9 15.77 1.20 + 10 17.37 1.27 + 11 19.70 0.57 + 12 19.73 0.44 + 13 19.73 0.44 + 14 20.00 0.00 + 15 19.93 0.25 + 16 20.00 0.00 diff --git a/docs/perf_tests/unfold_medium.dat b/docs/perf_tests/unfold_medium.dat new file mode 100644 index 000000000..0d93ed13a --- /dev/null +++ b/docs/perf_tests/unfold_medium.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 50.03 0.46 + 2 99.93 0.25 + 4 200.00 0.63 + 8 399.97 1.55 + 16 797.68 2.69 + 32 1388.09 20.02 diff --git a/docs/perf_tests/unfold_medium_saturation.dat b/docs/perf_tests/unfold_medium_saturation.dat new file mode 100644 index 000000000..9de051443 --- /dev/null +++ b/docs/perf_tests/unfold_medium_saturation.dat @@ -0,0 +1,17 @@ +# nthreads avg_rate rms + 1 35.66 2.89 + 2 72.30 1.29 + 3 106.47 1.54 + 4 141.67 1.25 + 5 176.93 1.91 + 6 212.30 1.29 + 7 245.67 2.15 + 8 280.43 4.61 + 9 314.37 4.13 + 10 348.40 3.03 + 11 384.67 2.49 + 12 395.90 2.22 + 13 396.83 1.75 + 14 397.47 0.88 + 15 395.50 4.05 + 16 391.37 5.31 diff --git a/docs/perf_tests/unfold_mini.dat b/docs/perf_tests/unfold_mini.dat new file mode 100644 index 000000000..efb2bc836 --- /dev/null +++ b/docs/perf_tests/unfold_mini.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 146191.03 1159.40 + 2 123631.97 1250.02 + 4 122254.20 3335.23 + 8 106006.57 2424.04 + 16 99135.43 2055.58 + 32 99163.60 987.07 diff --git a/docs/perf_tests/unfold_small.dat b/docs/perf_tests/unfold_small.dat new file mode 100644 index 000000000..34499c3f2 --- /dev/null +++ b/docs/perf_tests/unfold_small.dat @@ -0,0 +1,7 @@ +# nthreads avg_rate rms + 1 2450.25 4.38 + 2 4897.90 5.82 + 4 9768.87 9.73 + 8 19431.07 20.00 + 16 35987.13 876.49 + 32 28486.33 568.00 diff --git a/docs/perf_tests/unfold_small_saturation.dat b/docs/perf_tests/unfold_small_saturation.dat new file mode 100644 index 000000000..06fb2d39d --- /dev/null +++ b/docs/perf_tests/unfold_small_saturation.dat @@ -0,0 +1,17 @@ +# nthreads avg_rate rms + 1 1789.15 1.84 + 2 3549.03 2.71 + 3 5256.70 5.21 + 4 6953.33 12.23 + 5 8649.73 10.02 + 6 10343.23 20.45 + 7 11944.30 30.49 + 8 13586.83 36.57 + 9 15152.83 58.26 + 10 16452.90 58.52 + 11 17298.20 148.43 + 12 17247.50 95.88 + 13 17210.83 61.02 + 14 17172.87 245.58 + 15 17141.60 114.92 + 16 17160.97 122.61 diff --git a/scripts/jana-plot-scaletests.py b/scripts/jana-plot-scaletests.py index 171ac9fc7..e426da0f9 100755 --- a/scripts/jana-plot-scaletests.py +++ b/scripts/jana-plot-scaletests.py @@ -49,7 +49,7 @@ def make_plot(plot_spec, input_dir): tpar = subplot['t_par'] tseq = subplot['t_seq'] - nthreads = np.arange(minnthreads, maxnthreads+1, 1) + #nthreads = np.arange(minnthreads, maxnthreads+1, 1) seq_bottleneck = 1000 / tseq par_bottleneck = 1000 * nthreads / tpar amdahl_ys = 1000 / (tseq + (tpar/nthreads)) diff --git a/src/libraries/JANA/CLI/JBenchmarker.cc b/src/libraries/JANA/CLI/JBenchmarker.cc index d7298a8e7..46e59a7ce 100644 --- a/src/libraries/JANA/CLI/JBenchmarker.cc +++ b/src/libraries/JANA/CLI/JBenchmarker.cc @@ -60,6 +60,16 @@ JBenchmarker::JBenchmarker(JApplication* app) : m_app(app) { m_output_dir, "Output directory name for benchmark test results"); + params->SetDefaultParameter( + "benchmark:rates_filename", + m_rates_filename, + "Filename for benchmark rates"); + + params->SetDefaultParameter( + "benchmark:samples_filename", + m_samples_filename, + "Filename for benchmark samples"); + params->SetDefaultParameter( "benchmark:copyscript", m_copy_script, @@ -82,15 +92,17 @@ void JBenchmarker::RunUntilFinished() { << " benchmark:threadstep = " << m_thread_step << std::endl << " benchmark:use_log_scale = " << m_use_log_scale << std::endl << " benchmark:nsamples = " << m_nsamples << std::endl - << " benchmark:resultsdir = " << m_output_dir << std::endl; + << " benchmark:resultsdir = " << m_output_dir << std::endl + << " benchmark:rates_filename = " << m_rates_filename << std::endl + << " benchmark:samples_filename = " << m_samples_filename << std::endl; mkdir(m_output_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - std::ofstream samples_file(m_output_dir + "/samples.dat"); + std::ofstream samples_file(m_output_dir + "/" + m_samples_filename); samples_file << "# nthreads rate" << std::endl; - std::ofstream rates_file(m_output_dir + "/rates.dat"); + std::ofstream rates_file(m_output_dir + "/" + m_rates_filename); rates_file << "# nthreads avg_rate rms" << std::endl; diff --git a/src/libraries/JANA/CLI/JBenchmarker.h b/src/libraries/JANA/CLI/JBenchmarker.h index 1674b9aef..b73082a52 100644 --- a/src/libraries/JANA/CLI/JBenchmarker.h +++ b/src/libraries/JANA/CLI/JBenchmarker.h @@ -15,7 +15,10 @@ class JBenchmarker { unsigned m_thread_step = 1; unsigned m_nsamples = 15; std::string m_output_dir = "JANA_Test_Results"; + std::string m_rates_filename = "rates.dat"; + std::string m_samples_filename = "samples.dat"; bool m_copy_script = true; + bool m_include_samples = true; bool m_use_log_scale = false; public: diff --git a/src/libraries/JANA/Engine/JExecutionEngine.cc b/src/libraries/JANA/Engine/JExecutionEngine.cc index be3669cf2..60fd6a94e 100644 --- a/src/libraries/JANA/Engine/JExecutionEngine.cc +++ b/src/libraries/JANA/Engine/JExecutionEngine.cc @@ -495,7 +495,9 @@ void JExecutionEngine::ExchangeTask(Task& task, size_t worker_id, bool nonblocki // Notify one worker, who will notify the next, etc, as long as FindNextReadyTaskUnsafe() succeeds. // After FindNextReadyTaskUnsafe fails, all threads block until the next returning worker reactivates the // notification chain. - m_condvar.notify_one(); + if (task.arrow != nullptr && task.arrow->IsParallel()) { + m_condvar.notify_one(); + } } @@ -611,7 +613,7 @@ void JExecutionEngine::FindNextReadyTask_Unsafe(Task& task, WorkerState& worker) // Note that our worker threads will still wait at ExchangeTask() until they get // shut down separately during Scale(). - if (m_runstatus == RunStatus::Running || m_runstatus == RunStatus::Pausing || m_runstatus == RunStatus::Draining) { + if (m_runstatus == RunStatus::Pausing || m_runstatus == RunStatus::Draining) { // We want to avoid scenarios such as where the topology already Finished but then gets reset to Paused // This also leaves a cleaner narrative in the logs. diff --git a/src/libraries/JANA/JFactorySet.cc b/src/libraries/JANA/JFactorySet.cc index 461779526..712cc0cf9 100644 --- a/src/libraries/JANA/JFactorySet.cc +++ b/src/libraries/JANA/JFactorySet.cc @@ -235,7 +235,9 @@ void JFactorySet::Print() const { table | databundle->GetSize(); } } - table.Render(std::cout); + std::ostringstream oss; + table.Render(oss); + std::cout << oss.str(); } //--------------------------------- diff --git a/src/libraries/JANA/Utils/JBenchUtils.cc b/src/libraries/JANA/Utils/JBenchUtils.cc index 5f54d11d6..9bfe59ada 100644 --- a/src/libraries/JANA/Utils/JBenchUtils.cc +++ b/src/libraries/JANA/Utils/JBenchUtils.cc @@ -5,6 +5,7 @@ #include "JBenchUtils.h" #include +#include void JBenchUtils::set_seed(size_t event_number, std::string caller_name) @@ -74,6 +75,26 @@ uint64_t JBenchUtils::write_memory(std::vector& buffer, uint64_t bytes, do } +void JBenchUtils::consume_cpu_us(uint64_t microseconds) { + using clock = std::chrono::steady_clock; + auto deadline = clock::now() + std::chrono::microseconds(microseconds); + + volatile double acc = 1.0; // volatile: optimizer can't elide + while (clock::now() < deadline) { + // FMA is fast but not trivially free; 8 ops per loop body + // avoids tight branch-dominated loops that mispredict badly + acc = std::fma(acc, 1.0000001, 0.0000001); + acc = std::fma(acc, 1.0000001, 0.0000001); + acc = std::fma(acc, 1.0000001, 0.0000001); + acc = std::fma(acc, 1.0000001, 0.0000001); + acc = std::fma(acc, 1.0000001, 0.0000001); + acc = std::fma(acc, 1.0000001, 0.0000001); + acc = std::fma(acc, 1.0000001, 0.0000001); + acc = std::fma(acc, 1.0000001, 0.0000001); + } + // Prevent dead-store elimination at the call site too + asm volatile("" : : "r,m"(acc) : "memory"); +} diff --git a/src/libraries/JANA/Utils/JBenchUtils.h b/src/libraries/JANA/Utils/JBenchUtils.h index 71106d600..d3338ebbc 100644 --- a/src/libraries/JANA/Utils/JBenchUtils.h +++ b/src/libraries/JANA/Utils/JBenchUtils.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -28,4 +29,6 @@ class JBenchUtils { uint64_t read_memory(const std::vector& buffer); uint64_t write_memory(std::vector& buffer, uint64_t bytes, double spread=0.0); + static void consume_cpu_us(uint64_t microsecs); + }; diff --git a/src/programs/perf_tests/BasicTopology.cc b/src/programs/perf_tests/BasicTopology.cc new file mode 100644 index 000000000..c9e21a9aa --- /dev/null +++ b/src/programs/perf_tests/BasicTopology.cc @@ -0,0 +1,258 @@ +// Copyright 2022-2026, Jefferson Science Associates, LLC. +// Subject to the terms in the LICENSE file found in the top-level directory. + + +#define CATCH_CONFIG_MAIN +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace jana::perftest::basic { + +struct Data { size_t x; }; + +struct PESrc : public JEventSource { + + Output data_out {this}; + Parameter latency_us {this, "latency_us", 0}; + + PESrc() { + SetPrefix("src"); + SetCallbackStyle(CallbackStyle::ExpertMode); + data_out.SetShortName("1"); + } + JEventSource::Result Emit(JEvent& event) override { + data_out().push_back(new Data {event.GetEventNumber()*3 }); + JBenchUtils::consume_cpu_us(*latency_us); + return Result::Success; + }; +}; + +struct PEFac : public JFactory { + Input data_in {this}; + Output data_out {this}; + Parameter latency_us {this, "latency_us", 0}; + PEFac() { + SetPrefix("fac"); + SetLevel(JEventLevel::PhysicsEvent); + data_in.SetDatabundleName("1"); + data_out.SetShortName("2"); + } + void Process(const JEvent&) override { + auto x = data_in().at(0)->x * 10; + data_out().push_back(new Data {x}); + JBenchUtils::consume_cpu_us(*latency_us); + }; +}; + +struct PEProc : public JEventProcessor { + Input data_in {this}; + Parameter latency_us {this, "latency_us", 0}; + PEProc() { + SetPrefix("proc"); + SetLevel(JEventLevel::PhysicsEvent); + SetCallbackStyle(CallbackStyle::ExpertMode); + data_in.SetDatabundleName("2"); + } + void ProcessSequential(const JEvent&) override { + (void) (data_in().at(0)->x); + JBenchUtils::consume_cpu_us(*latency_us); + }; +}; + + +TEST_CASE("BasicTopology_Mini") { + + LOG << "Running BasicTopology_Mini"; + + JApplication app; + app.SetParameterValue("src:latency_us", 0); // Infinity Hz + app.SetParameterValue("fac:latency_us", 0); // Infinity Hz + app.SetParameterValue("proc:latency_us", 0); // Infinity Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "basic_mini.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + app.Add(new PESrc); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("BasicTopology_Small") { + + LOG << "Running BasicTopology_Small"; + + JApplication app; + app.SetParameterValue("src:latency_us", 0); + app.SetParameterValue("fac:latency_us", 1000000/5000); // 5 kHz + app.SetParameterValue("proc:latency_us", 0); + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "basic_small.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + app.Add(new PESrc); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("BasicTopology_Small_Saturation") { + + LOG << "Running BasicTopology_Small_Saturation"; + + JApplication app; + app.SetParameterValue("src:latency_us", 1'000'000 / 40'000); // 40 kHz + app.SetParameterValue("fac:latency_us", 1'000'000 / 5000); // 5 kHz + app.SetParameterValue("proc:latency_us", 1'000'000 / 40'000); // 40 kHz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "basic_small_saturation.dat"); + app.SetParameterValue("benchmark:use_log_scale", false); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "16"); + + app.Add(new PESrc); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("BasicTopology_Medium") { + + LOG << "Running BasicTopology_Medium"; + + JApplication app; + app.SetParameterValue("src:latency_us", 0); + app.SetParameterValue("fac:latency_us", 1000000/50); // 50 Hz + app.SetParameterValue("proc:latency_us", 0); + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "basic_medium.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + app.Add(new PESrc); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("BasicTopology_Medium_Saturation") { + + LOG << "Running BasicTopology_Medium_Saturation"; + + JApplication app; + app.SetParameterValue("src:latency_us", 1'000'000 / 400); // 400 Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 50); // 50 Hz + app.SetParameterValue("proc:latency_us", 1'000'000 / 400); // 400 Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "basic_medium_saturation.dat"); + app.SetParameterValue("benchmark:use_log_scale", false); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "16"); + + app.Add(new PESrc); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} +TEST_CASE("BasicTopology_Large") { + + LOG << "Running BasicTopology_Large"; + + JApplication app; + app.SetParameterValue("src:latency_us", 0); // Infinity Hz + app.SetParameterValue("fac:latency_us", 1000000/5); // 5 Hz + app.SetParameterValue("proc:latency_us", 0); // 100 Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "basic_large.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + app.Add(new PESrc); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("BasicTopology_Large_Saturation") { + + LOG << "Running BasicTopology_Large_Saturation"; + + JApplication app; + app.SetParameterValue("src:latency_us", 1'000'000/40); // 40 Hz + app.SetParameterValue("fac:latency_us", 1'000'000/5); // 5 Hz + app.SetParameterValue("proc:latency_us", 1'000'000/40); // 40 Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "basic_large_saturation.dat"); + app.SetParameterValue("benchmark:use_log_scale", false); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "16"); + + app.Add(new PESrc); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + + +TEST_CASE("BasicTopology_JTest") { + // 5Hz for full reconstruction + // 20kHz for stripped-down reconstruction (not per-core) + // Base memory allcation: 100 MB/core + 600MB + // 1 thread/event, disentangle 1 event, turn into 40. + // disentangled (single event size) : 12.5 kB / event (before blown up) + // entangled "block of 40": dis * 40 + + auto params = new JParameterManager; + params->SetParameter("jana:loglevel", "off"); + + // Log levels get set as soon as JApp gets constructed + params->SetParameter("jtest:parser:cputime_ms", 2); + params->SetParameter("jtest:plotter:cputime_ms", 2); + + params->SetParameter("benchmark:resultsdir", "docs/perf_tests"); + params->SetParameter("benchmark:rates_filename", "basic_jtest.dat"); + params->SetParameter("benchmark:use_log_scale", true); + params->SetParameter("benchmark:minthreads", "1"); + params->SetParameter("benchmark:maxthreads", "32"); + + JApplication app(params); + auto logger = params->GetLogger("PerfTests"); + app.AddPlugin("JTest"); + + LOG_WARN(logger) << "Running JTest tuned to imitate halld_recon" << LOG_END; + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + + +} // namespace + + diff --git a/src/programs/perf_tests/CMakeLists.txt b/src/programs/perf_tests/CMakeLists.txt index de6ebde60..3c25c5266 100644 --- a/src/programs/perf_tests/CMakeLists.txt +++ b/src/programs/perf_tests/CMakeLists.txt @@ -7,7 +7,7 @@ if (USE_PODIO) target_link_libraries(jana-perf-tests PRIVATE PodioDatamodel PodioDatamodelDict) else() - message(STATUS "jana-perf-tests compiled without PODIO stress test because USE_PODIO=Off") + message(STATUS "jana-perf-tests compiled without PODIO because USE_PODIO=Off") endif() diff --git a/src/programs/perf_tests/PerfTests.cc b/src/programs/perf_tests/PerfTests.cc deleted file mode 100644 index 4395a12af..000000000 --- a/src/programs/perf_tests/PerfTests.cc +++ /dev/null @@ -1,109 +0,0 @@ - -// Copyright 2022, Jefferson Science Associates, LLC. -// Subject to the terms in the LICENSE file found in the top-level directory. - - -// PerfTests is designed to make it easy to see how changes to JANA's internals affect its performance on -// a variety of workloads we care about. - -#include -#include -#include -#if HAVE_PODIO -#include -#endif - - - -int main() { - - { - - // 5Hz for full reconstruction - // 20kHz for stripped-down reconstruction (not per-core) - // Base memory allcation: 100 MB/core + 600MB - // 1 thread/event, disentangle 1 event, turn into 40. - // disentangled (single event size) : 12.5 kB / event (before blown up) - // entangled "block of 40": dis * 40 - - auto params = new JParameterManager; - params->SetParameter("jana:loglevel", "off"); - - // Log levels get set as soon as JApp gets constructed - params->SetParameter("jtest:write_csv", false); - params->SetParameter("jtest:parser_ms", 2); - params->SetParameter("jtest:plotter_ms", 2); - - params->SetParameter("benchmark:resultsdir", "perftest_fake_halldrecon"); - - JApplication app(params); - auto logger = params->GetLogger("PerfTests"); - app.AddPlugin("JTest"); - - LOG_INFO(logger) << "Running JTest tuned to imitate halld_recon" << LOG_END; - JBenchmarker benchmarker(&app); - benchmarker.RunUntilFinished(); - } - - - { - - auto params = new JParameterManager; - params->SetParameter("jana:loglevel", "off"); - - // Log levels get set as soon as JApp gets constructed - params->SetParameter("jtest:write_csv", false); - - params->SetParameter("jtest:parser_ms", 0); - params->SetParameter("jtest:parser_spread", 0); - params->SetParameter("jtest:parser_bytes", 0); - params->SetParameter("jtest:parser_bytes_spread", 0); - - params->SetParameter("jtest:disentangler_ms", 0); - params->SetParameter("jtest:disentangler_spread", 0); - params->SetParameter("jtest:disentangler_bytes", 0); - params->SetParameter("jtest:disentangler_bytes_spread", 0); - - params->SetParameter("jtest:tracker_ms", 0); - params->SetParameter("jtest:tracker_spread", 0); - params->SetParameter("jtest:tracker_bytes", 0); - params->SetParameter("jtest:tracker_bytes_spread", 0); - - params->SetParameter("jtest:plotter_ms", 0); - params->SetParameter("jtest:plotter_spread", 0); - params->SetParameter("jtest:plotter_bytes", 0); - params->SetParameter("jtest:plotter_bytes_spread", 0); - - params->SetParameter("benchmark:resultsdir", "perftest_pure_overhead"); - - JApplication app(params); - auto logger = params->GetLogger("PerfTests"); - app.AddPlugin("JTest"); - - LOG_INFO(logger) << "Running JTest with all sleeps and computations turned off" << LOG_END; - JBenchmarker benchmarker(&app); - benchmarker.RunUntilFinished(); - } - -#if HAVE_PODIO - { - // Test that we can link against PODIO datamodel - // TODO: Delete me - ExampleHitCollection c; - - auto params = new JParameterManager; - params->SetParameter("jana:loglevel", "off"); - JApplication app(params); - auto logger = params->GetLogger("PerfTests"); - // TODO: Add Podio sources, processors, and factories just like JTest - LOG_INFO(logger) << "Running PODIO stress test" << LOG_END; - JBenchmarker benchmarker(&app); - benchmarker.RunUntilFinished(); - } -#endif - - // Next: Run with subevents - // Next: Run with more and more arrows to see how that scales - // Next: Barrier events - -} diff --git a/src/programs/perf_tests/PodioStressTest.h b/src/programs/perf_tests/PodioStressTest.h deleted file mode 100644 index 7df870772..000000000 --- a/src/programs/perf_tests/PodioStressTest.h +++ /dev/null @@ -1,7 +0,0 @@ - -#pragma once - -#include -#include - - diff --git a/src/programs/perf_tests/SourceTopology.cc b/src/programs/perf_tests/SourceTopology.cc new file mode 100644 index 000000000..63d603d49 --- /dev/null +++ b/src/programs/perf_tests/SourceTopology.cc @@ -0,0 +1,93 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace jana::perftest::source { + +struct Data { size_t x; }; + +struct Src : public JEventSource { + + Parameter latency_us {this, "latency_us", 0}; + Output data_out {this}; + + Src() { + SetPrefix("sut"); + SetCallbackStyle(CallbackStyle::ExpertMode); + data_out.SetShortName("1"); + } + JEventSource::Result Emit(JEvent& block) override { + data_out().push_back(new Data {block.GetEventNumber()*3 }); + JBenchUtils::consume_cpu_us(*latency_us); + return Result::Success; + }; +}; + +TEST_CASE("SourceTopology_Mini") { + LOG << "Running SourceTopology_Mini"; + JApplication app; + app.SetParameterValue("sut:latency_us", 0); // Infinity Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "source_mini.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + app.Add(new Src); + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("SourceTopology_Small") { + LOG << "Running SourceTopology_Small"; + JApplication app; + app.SetParameterValue("sut:latency_us", 50); // 20 kHz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "source_small.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + app.Add(new Src); + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("SourceTopology_Medium") { + LOG << "Running SourceTopology_Medium"; + JApplication app; + app.SetParameterValue("sut:latency_us", 10000); // 100 Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "source_medium.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + app.Add(new Src); + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("SourceTopology_Large") { + LOG << "Running SourceTopology_Large"; + JApplication app; + app.SetParameterValue("sut:latency_us", 200000); // 5 Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "source_large.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + app.Add(new Src); + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +} + + + diff --git a/src/programs/perf_tests/TapChainTopology.cc b/src/programs/perf_tests/TapChainTopology.cc new file mode 100644 index 000000000..b38dc9363 --- /dev/null +++ b/src/programs/perf_tests/TapChainTopology.cc @@ -0,0 +1,372 @@ + +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace jana::perftest::tapchain { + +struct Data { size_t x; }; + +struct Src : public JEventSource { + + Output data_out {this}; + Parameter latency_us {this, "latency_us", 0}; + + Src() { + SetPrefix("src"); + SetCallbackStyle(CallbackStyle::ExpertMode); + data_out.SetShortName("1"); + } + JEventSource::Result Emit(JEvent& evt) override { + data_out().push_back(new Data {evt.GetEventNumber()*3 }); + JBenchUtils::consume_cpu_us(*latency_us); + return Result::Success; + }; +}; + +struct Fac : public JFactory { + Input data_in {this}; + Output data_out {this}; + Parameter latency_us {this, "latency_us", 0}; + + Fac() { + SetPrefix("fac"); + data_in.SetDatabundleName("1"); + data_out.SetShortName("2"); + } + void Process(const JEvent&) override { + auto x = data_in().at(0)->x + 7; + data_out().push_back(new Data {x}); + JBenchUtils::consume_cpu_us(*latency_us); + }; +}; + +struct Proc : public JEventProcessor { + Input data_in {this}; + Parameter latency_us {this, "latency_us", 0}; + Proc() { + SetPrefix("proc"); + SetCallbackStyle(CallbackStyle::ExpertMode); + data_in.SetDatabundleName("2"); + } + void ProcessSequential(const JEvent&) override { + (void) (data_in().at(0)->x); + JBenchUtils::consume_cpu_us(*latency_us); + }; +}; + + +TEST_CASE("TapChainTopology_1_Mini") { + + LOG << "Running TapChainTopology_1_Mini"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + app.Add(new Proc); + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 0); // Inf Hz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_1_mini.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_4_Mini") { + + LOG << "Running TapChainTopology_4_Mini"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<4; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_4_mini.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_16_Mini") { + + LOG << "Running TapChainTopology_16_Mini"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<16; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 0); // Inf Hz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_16_mini.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_1_Small") { + + LOG << "Running TapChainTopology_1_Small"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + app.Add(new Proc); + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 5000); // 5 kHz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_1_small.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_4_Small") { + + LOG << "Running TapChainTopology_4_Small"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<4; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 5000); // 5 kHz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_4_small.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_16_Small") { + + LOG << "Running TapChainTopology_16_Small"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<16; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 5000); // 5 kHz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_16_small.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + + +TEST_CASE("TapChainTopology_1_Medium") { + + LOG << "Running TapChainTopology_1_Medium"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + app.Add(new Proc); + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 100); // 100 Hz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_1_medium.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_4_Medium") { + + LOG << "Running TapChainTopology_4_Medium"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<4; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 100); // 100 Hz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_4_medium.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_16_Medium") { + + LOG << "Running TapChainTopology_16_Medium"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<16; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 100); // 100 Hz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_16_medium.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_1_Large") { + + LOG << "Running TapChainTopology_1_Large"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + app.Add(new Proc); + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 5); // 5 Hz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_1_large.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_4_Large") { + + LOG << "Running TapChainTopology_4_Large"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<4; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 5); // 5 Hz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_4_large.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_16_Large") { + + LOG << "Running TapChainTopology_16_Large"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<16; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("src:latency_us", 0); // Inf Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 5); // 5 Hz + app.SetParameterValue("proc:latency_us", 0); // Inf Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_16_large.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("TapChainTopology_Pipelining") { + + LOG << "Running TapChainTopology_Pipelining"; + + JApplication app; + app.Add(new Src); + app.Add(new JFactoryGeneratorT); + for (int i=0; i<4; ++i) { + app.Add(new Proc); + } + + app.SetParameterValue("src:latency_us", 1'000'000 / 100); // 100 Hz + app.SetParameterValue("fac:latency_us", 1'000'000 / 100); // 100 Hz + app.SetParameterValue("proc:latency_us", 1'000'000 / 100); // 100 Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "tapchain_pipelining.dat"); + app.SetParameterValue("benchmark:use_log_scale", false); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "16"); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + + +} + + + diff --git a/src/programs/perf_tests/UnfoldTopology.cc b/src/programs/perf_tests/UnfoldTopology.cc new file mode 100644 index 000000000..918fc41e9 --- /dev/null +++ b/src/programs/perf_tests/UnfoldTopology.cc @@ -0,0 +1,293 @@ + +#include "JANA/Utils/JEventLevel.h" +#include + +#include +#include +#include +#include +#include +#include +#include + + +namespace jana::perftest::unfold { + +struct Data { size_t x; }; + +struct BSrc : public JEventSource { + + Output data_out {this}; + Parameter latency_us {this, "latency_us", 0}; + + BSrc() { + SetPrefix("bsrc"); + SetLevel(JEventLevel::Block); + SetCallbackStyle(CallbackStyle::ExpertMode); + data_out.SetShortName("1"); + } + JEventSource::Result Emit(JEvent& block) override { + data_out().push_back(new Data {block.GetEventNumber()*3 }); + JBenchUtils::consume_cpu_us(*latency_us); + return Result::Success; + }; +}; + +struct BFac : public JFactory { + Input data_in {this}; + Output data_out {this}; + Parameter latency_us {this, "latency_us", 0}; + + BFac() { + SetPrefix("bfac"); + SetLevel(JEventLevel::Block); + data_in.SetDatabundleName("1"); + data_out.SetShortName("2"); + } + void Process(const JEvent&) override { + auto x = data_in().at(0)->x + 7; + data_out().push_back(new Data {x}); + JBenchUtils::consume_cpu_us(*latency_us); + }; +}; + +struct Unf : public JEventUnfolder { + Input parent_data_in {this}; + Output child_data_out {this}; + Parameter latency_us {this, "latency_us", 0}; + + Unf() { + SetPrefix("unf"); + SetParentLevel(JEventLevel::Block); + SetChildLevel(JEventLevel::PhysicsEvent); + SetCallbackStyle(CallbackStyle::ExpertMode); + parent_data_in.SetDatabundleName("2"); + child_data_out.SetShortName("3"); + } + JEventUnfolder::Result Unfold(const JEvent&, JEvent&, int child_nr) override { + auto x = parent_data_in().at(0)->x * 10 + child_nr; + child_data_out().push_back(new Data{x}); + JBenchUtils::consume_cpu_us(*latency_us); + + if (child_nr == 9) { + return Result::NextChildNextParent; + } + return Result::NextChildKeepParent; + }; +}; + +struct PEFac : public JFactory { + Input data_in {this}; + Output data_out {this}; + Parameter latency_us {this, "latency_us", 0}; + PEFac() { + SetPrefix("pefac"); + SetLevel(JEventLevel::PhysicsEvent); + data_in.SetDatabundleName("3"); + data_out.SetShortName("4"); + } + void Process(const JEvent&) override { + auto x = data_in().at(0)->x * 10; + data_out().push_back(new Data {x}); + JBenchUtils::consume_cpu_us(*latency_us); + }; +}; + +struct PEProc : public JEventProcessor { + Input data_in {this}; + Parameter latency_us {this, "latency_us", 0}; + PEProc() { + SetPrefix("peproc"); + SetLevel(JEventLevel::PhysicsEvent); + SetCallbackStyle(CallbackStyle::ExpertMode); + data_in.SetDatabundleName("4"); + } + void ProcessSequential(const JEvent&) override { + (void) (data_in().at(0)->x); + JBenchUtils::consume_cpu_us(*latency_us); + }; +}; + + +TEST_CASE("UnfoldTopology_Mini") { + + LOG << "Running UnfoldTopology_Mini"; + + JApplication app; + app.SetParameterValue("bsrc:latency_us", 0); // Infinity Hz + app.SetParameterValue("bfac:latency_us", 0); // Infinity Hz + app.SetParameterValue("unf:latency_us", 0); // Infinity Hz + app.SetParameterValue("pefac:latency_us", 0); // Infinity Hz + app.SetParameterValue("peproc:latency_us", 0); // Infinity Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "unfold_mini.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + app.Add(new BSrc); + app.Add(new Unf); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("UnfoldTopology_Small") { + LOG << "Running UnfoldTopology_Small"; + + JApplication app; + app.SetParameterValue("bsrc:latency_us", 0); // Infinity Hz + app.SetParameterValue("bfac:latency_us", 1'000'000 / 500); // 500 Hz + app.SetParameterValue("unf:latency_us", 0); // Infinity Hz + app.SetParameterValue("pefac:latency_us", 1'000'000 / 5000); // 5 kHz + app.SetParameterValue("peproc:latency_us", 0); // Infinity Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "unfold_small.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + app.Add(new BSrc); + app.Add(new Unf); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("UnfoldTopology_Small_Saturation") { + LOG << "Running UnfoldTopology_Small_Saturation"; + + JApplication app; + app.SetParameterValue("bsrc:latency_us", 1'000'000 / 2'000); // 2 kHz + app.SetParameterValue("bfac:latency_us", 1'000'000 / 500); // 500 Hz + app.SetParameterValue("unf:latency_us", 1'000'000 / 20'000); // 20 kHz + app.SetParameterValue("pefac:latency_us", 1'000'000 / 5000); // 5 kHz + app.SetParameterValue("peproc:latency_us", 1'000'000 / 20'000); // 20 kHz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "unfold_small_saturation.dat"); + app.SetParameterValue("benchmark:use_log_scale", false); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "16"); + + app.Add(new BSrc); + app.Add(new Unf); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("UnfoldTopology_Medium") { + LOG << "Running UnfoldTopology_Medium"; + + JApplication app; + app.SetParameterValue("bsrc:latency_us", 0); // Infinity Hz + app.SetParameterValue("bfac:latency_us", 1'000'000 / 10); // 10 Hz + app.SetParameterValue("unf:latency_us", 0); // Infinity Hz + app.SetParameterValue("pefac:latency_us", 1'000'000 / 100); // 100 Hz + app.SetParameterValue("peproc:latency_us", 0); // Infinity Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "unfold_medium.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + app.Add(new BSrc); + app.Add(new Unf); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("UnfoldTopology_Medium_Saturation") { + LOG << "Running UnfoldTopology_Medium"; + + JApplication app; + app.SetParameterValue("bsrc:latency_us", 1'000'000 / 40); // 40 Hz + app.SetParameterValue("bfac:latency_us", 1'000'000 / 10); // 10 Hz + app.SetParameterValue("unf:latency_us", 1'000'000 / 400); // 400 Hz + app.SetParameterValue("pefac:latency_us", 1'000'000 / 100); // 100 Hz + app.SetParameterValue("peproc:latency_us", 1'000'000 / 400); // 400 Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "unfold_medium_saturation.dat"); + app.SetParameterValue("benchmark:use_log_scale", false); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "16"); + + app.Add(new BSrc); + app.Add(new Unf); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + +TEST_CASE("UnfoldTopology_Large") { + LOG << "Running UnfoldTopology_Large"; + + JApplication app; + app.SetParameterValue("bsrc:latency_us", 0); // Infinity Hz + app.SetParameterValue("bfac:latency_us", 1'000'000*2); // 0.5 Hz + app.SetParameterValue("unf:latency_us", 0); // Infinity Hz + app.SetParameterValue("pefac:latency_us", 1'000'000 / 5); // 5 Hz + app.SetParameterValue("peproc:latency_us", 0); // Infinity Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "unfold_large.dat"); + app.SetParameterValue("benchmark:use_log_scale", true); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "32"); + + app.Add(new BSrc); + app.Add(new Unf); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + + +TEST_CASE("UnfoldTopology_Large_Saturation") { + LOG << "Running UnfoldTopology_Large_Saturation"; + + JApplication app; + app.SetParameterValue("bsrc:latency_us", 1'000'000 / 2); // 2 Hz + app.SetParameterValue("bfac:latency_us", 1'000'000*2); // 0.5 Hz + app.SetParameterValue("unf:latency_us", 1'000'000 / 20); // 20 Hz + app.SetParameterValue("pefac:latency_us", 1'000'000 / 5); // 5 Hz + app.SetParameterValue("peproc:latency_us", 1'000'000 / 20); // 20 Hz + app.SetParameterValue("benchmark:resultsdir", "docs/perf_tests"); + app.SetParameterValue("benchmark:rates_filename", "unfold_large_saturation.dat"); + app.SetParameterValue("benchmark:use_log_scale", false); + app.SetParameterValue("benchmark:minthreads", "1"); + app.SetParameterValue("benchmark:maxthreads", "16"); + + app.Add(new BSrc); + app.Add(new Unf); + app.Add(new PEProc); + app.Add(new JFactoryGeneratorT); + app.Add(new JFactoryGeneratorT); + + JBenchmarker benchmarker(&app); + benchmarker.RunUntilFinished(); +} + + +} + + +