From 3144c92520122ca34aa1d5e97f4848febccbf20b Mon Sep 17 00:00:00 2001 From: Lutetium-Vanadium Date: Sat, 10 Jun 2023 16:16:02 +0800 Subject: [PATCH 1/3] Update the matrix size benchmarking scripts This commit also adds the figures gotten from running the benchmarks. Note that 100,000 was removed from scanAColCPP due to CSRV2 causing an out of memory error. --- benchmark/scripts/scanACol/config_BCoAMM.csv | 3 +- benchmark/scripts/scanACol/config_BerCRS.csv | 3 +- benchmark/scripts/scanACol/config_CPPCRS.csv | 8 --- benchmark/scripts/scanACol/config_CRS.csv | 3 +- .../config_CRSV2.csv} | 3 +- benchmark/scripts/scanACol/config_CoAMM.csv | 3 +- .../scripts/scanACol/config_CounterSketch.csv | 1 + benchmark/scripts/scanACol/config_EWS.csv | 3 +- benchmark/scripts/scanACol/config_RAWMM.csv | 3 +- .../config_TugOfWar.csv} | 3 +- benchmark/scripts/scanACol/config_WCR.csv | 3 +- benchmark/scripts/scanACol/drawTogether.py | 15 +++--- .../scripts/scanAColCPP/config_CPPBCOOFD.csv | 10 ++++ .../scripts/scanAColCPP/config_CPPBCRS.csv | 10 ++++ .../scripts/scanAColCPP/config_CPPCRSV2.csv | 10 ++++ .../scripts/scanAColCPP/config_CPPINT8.csv | 10 ++++ .../scripts/scanAColCPP/config_CPPSMPPCA.csv | 9 ++++ .../scanAColCPP/config_CPPWeightedCR.csv | 9 ++++ .../scripts/scanAColCPP/config_CoAMM.csv | 6 --- .../scanAColCPP/config_CounterSketch.csv | 6 --- benchmark/scripts/scanAColCPP/config_EWS.csv | 6 --- .../scripts/scanAColCPP/config_FDAMM.csv | 6 --- .../scripts/scanAColCPP/config_RAWMM.csv | 6 --- benchmark/scripts/scanAColCPP/config_WCR.csv | 6 --- benchmark/scripts/scanAColCPP/drawTogether.py | 48 ++++++++++++----- benchmark/scripts/scanARow/config_BCoAMM.csv | 3 +- benchmark/scripts/scanARow/config_BerCRS.csv | 3 +- benchmark/scripts/scanARow/config_CRS.csv | 3 +- .../config_CRSV2.csv} | 3 +- benchmark/scripts/scanARow/config_CoAMM.csv | 3 +- .../scripts/scanARow/config_CounterSketch.csv | 1 + benchmark/scripts/scanARow/config_EWS.csv | 3 +- benchmark/scripts/scanARow/config_FDAMM.csv | 6 --- benchmark/scripts/scanARow/config_RAWMM.csv | 3 +- .../config_TugOfWar.csv} | 3 +- benchmark/scripts/scanARow/config_WCR.csv | 3 +- benchmark/scripts/scanARow/drawTogether.py | 15 +++--- .../scripts/scanARowCPP/config_BCoAMM.csv | 6 --- .../scripts/scanARowCPP/config_BerCRS.csv | 6 --- .../scripts/scanARowCPP/config_CPPBCOOFD.csv | 10 ++++ .../scripts/scanARowCPP/config_CPPBCRS.csv | 10 ++++ .../scanARowCPP/config_CPPCOUNTERSKETCH.csv | 2 +- .../scripts/scanARowCPP/config_CPPCRSV2.csv | 10 ++++ .../scripts/scanARowCPP/config_CPPINT8.csv | 10 ++++ .../scripts/scanARowCPP/config_CPPSMPPCA.csv | 9 ++++ .../scanARowCPP/config_CPPWeightedCR.csv | 9 ++++ benchmark/scripts/scanARowCPP/config_CRS.csv | 6 --- .../scripts/scanARowCPP/config_CoAMM.csv | 6 --- .../scanARowCPP/config_CounterSketch.csv | 6 --- benchmark/scripts/scanARowCPP/config_EWS.csv | 6 --- .../scripts/scanARowCPP/config_FDAMM.csv | 6 --- .../scripts/scanARowCPP/config_RAWMM.csv | 6 --- benchmark/scripts/scanARowCPP/config_WCR.csv | 6 --- benchmark/scripts/scanARowCPP/drawTogether.py | 49 ++++++++++++++---- figures/aCol/aColsampling_cacheMiss.pdf | Bin 0 -> 9810 bytes figures/aCol/aColsampling_elapsedTime.pdf | Bin 0 -> 9913 bytes figures/aCol/aColsketch_cacheMiss.pdf | Bin 0 -> 9371 bytes figures/aCol/aColsketch_elapsedTime.pdf | Bin 0 -> 9612 bytes figures/aColCPP/aCol_ebRatio.pdf | Bin 0 -> 9922 bytes figures/aColCPP/aCol_froError.pdf | Bin 0 -> 10018 bytes .../aColCPP/aColsampling_cpp_cacheMiss.pdf | Bin 0 -> 10151 bytes .../aColCPP/aColsampling_cpp_elapsedTime.pdf | Bin 0 -> 10094 bytes figures/aColCPP/aColsketch_cpp_cacheMiss.pdf | Bin 0 -> 9768 bytes figures/aColCPP/aColsketch_cpp_ebRatio.pdf | Bin 0 -> 9612 bytes .../aColCPP/aColsketch_cpp_elapsedTime.pdf | Bin 0 -> 10020 bytes figures/aColCPP/aColsketch_cpp_froError.pdf | Bin 0 -> 9658 bytes figures/aRow/aRowsampling_cacheMiss.pdf | Bin 0 -> 9825 bytes figures/aRow/aRowsampling_elapsedTime.pdf | Bin 0 -> 10046 bytes figures/aRow/aRowsketch_cacheMiss.pdf | Bin 0 -> 9368 bytes figures/aRow/aRowsketch_elapsedTime.pdf | Bin 0 -> 9558 bytes .../aRowCPP/aRowsampling_cpp_cacheMiss.pdf | Bin 0 -> 10507 bytes figures/aRowCPP/aRowsampling_cpp_ebRatio.pdf | Bin 0 -> 10151 bytes .../aRowCPP/aRowsampling_cpp_elapsedTime.pdf | Bin 0 -> 10395 bytes figures/aRowCPP/aRowsampling_cpp_froError.pdf | Bin 0 -> 10355 bytes figures/aRowCPP/aRowsketch_cpp_cacheMiss.pdf | Bin 0 -> 10086 bytes figures/aRowCPP/aRowsketch_cpp_ebRatio.pdf | Bin 0 -> 9691 bytes .../aRowCPP/aRowsketch_cpp_elapsedTime.pdf | Bin 0 -> 10338 bytes figures/aRowCPP/aRowsketch_cpp_froError.pdf | Bin 0 -> 9954 bytes 78 files changed, 245 insertions(+), 160 deletions(-) delete mode 100644 benchmark/scripts/scanACol/config_CPPCRS.csv rename benchmark/scripts/{scanAColCPP/config_CRS.csv => scanACol/config_CRSV2.csv} (61%) rename benchmark/scripts/{scanAColCPP/config_BCoAMM.csv => scanACol/config_TugOfWar.csv} (59%) create mode 100644 benchmark/scripts/scanAColCPP/config_CPPBCOOFD.csv create mode 100644 benchmark/scripts/scanAColCPP/config_CPPBCRS.csv create mode 100644 benchmark/scripts/scanAColCPP/config_CPPCRSV2.csv create mode 100644 benchmark/scripts/scanAColCPP/config_CPPINT8.csv create mode 100644 benchmark/scripts/scanAColCPP/config_CPPSMPPCA.csv create mode 100644 benchmark/scripts/scanAColCPP/config_CPPWeightedCR.csv delete mode 100644 benchmark/scripts/scanAColCPP/config_CoAMM.csv delete mode 100644 benchmark/scripts/scanAColCPP/config_CounterSketch.csv delete mode 100644 benchmark/scripts/scanAColCPP/config_EWS.csv delete mode 100644 benchmark/scripts/scanAColCPP/config_FDAMM.csv delete mode 100644 benchmark/scripts/scanAColCPP/config_RAWMM.csv delete mode 100644 benchmark/scripts/scanAColCPP/config_WCR.csv rename benchmark/scripts/{scanACol/config_FDAMM.csv => scanARow/config_CRSV2.csv} (61%) delete mode 100644 benchmark/scripts/scanARow/config_FDAMM.csv rename benchmark/scripts/{scanAColCPP/config_BerCRS.csv => scanARow/config_TugOfWar.csv} (59%) delete mode 100644 benchmark/scripts/scanARowCPP/config_BCoAMM.csv delete mode 100644 benchmark/scripts/scanARowCPP/config_BerCRS.csv create mode 100644 benchmark/scripts/scanARowCPP/config_CPPBCOOFD.csv create mode 100644 benchmark/scripts/scanARowCPP/config_CPPBCRS.csv create mode 100644 benchmark/scripts/scanARowCPP/config_CPPCRSV2.csv create mode 100644 benchmark/scripts/scanARowCPP/config_CPPINT8.csv create mode 100644 benchmark/scripts/scanARowCPP/config_CPPSMPPCA.csv create mode 100644 benchmark/scripts/scanARowCPP/config_CPPWeightedCR.csv delete mode 100644 benchmark/scripts/scanARowCPP/config_CRS.csv delete mode 100644 benchmark/scripts/scanARowCPP/config_CoAMM.csv delete mode 100644 benchmark/scripts/scanARowCPP/config_CounterSketch.csv delete mode 100644 benchmark/scripts/scanARowCPP/config_EWS.csv delete mode 100644 benchmark/scripts/scanARowCPP/config_FDAMM.csv delete mode 100644 benchmark/scripts/scanARowCPP/config_RAWMM.csv delete mode 100644 benchmark/scripts/scanARowCPP/config_WCR.csv create mode 100644 figures/aCol/aColsampling_cacheMiss.pdf create mode 100644 figures/aCol/aColsampling_elapsedTime.pdf create mode 100644 figures/aCol/aColsketch_cacheMiss.pdf create mode 100644 figures/aCol/aColsketch_elapsedTime.pdf create mode 100644 figures/aColCPP/aCol_ebRatio.pdf create mode 100644 figures/aColCPP/aCol_froError.pdf create mode 100644 figures/aColCPP/aColsampling_cpp_cacheMiss.pdf create mode 100644 figures/aColCPP/aColsampling_cpp_elapsedTime.pdf create mode 100644 figures/aColCPP/aColsketch_cpp_cacheMiss.pdf create mode 100644 figures/aColCPP/aColsketch_cpp_ebRatio.pdf create mode 100644 figures/aColCPP/aColsketch_cpp_elapsedTime.pdf create mode 100644 figures/aColCPP/aColsketch_cpp_froError.pdf create mode 100644 figures/aRow/aRowsampling_cacheMiss.pdf create mode 100644 figures/aRow/aRowsampling_elapsedTime.pdf create mode 100644 figures/aRow/aRowsketch_cacheMiss.pdf create mode 100644 figures/aRow/aRowsketch_elapsedTime.pdf create mode 100644 figures/aRowCPP/aRowsampling_cpp_cacheMiss.pdf create mode 100644 figures/aRowCPP/aRowsampling_cpp_ebRatio.pdf create mode 100644 figures/aRowCPP/aRowsampling_cpp_elapsedTime.pdf create mode 100644 figures/aRowCPP/aRowsampling_cpp_froError.pdf create mode 100644 figures/aRowCPP/aRowsketch_cpp_cacheMiss.pdf create mode 100644 figures/aRowCPP/aRowsketch_cpp_ebRatio.pdf create mode 100644 figures/aRowCPP/aRowsketch_cpp_elapsedTime.pdf create mode 100644 figures/aRowCPP/aRowsketch_cpp_froError.pdf diff --git a/benchmark/scripts/scanACol/config_BCoAMM.csv b/benchmark/scripts/scanACol/config_BCoAMM.csv index aa481d3d..797a3c25 100644 --- a/benchmark/scripts/scanACol/config_BCoAMM.csv +++ b/benchmark/scripts/scanACol/config_BCoAMM.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/BetaCoOccurringFD.pt,String \ No newline at end of file +ptFile,torchscripts/BetaCoOccurringFD.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/config_BerCRS.csv b/benchmark/scripts/scanACol/config_BerCRS.csv index 14a0cdc1..4d9e7feb 100644 --- a/benchmark/scripts/scanACol/config_BerCRS.csv +++ b/benchmark/scripts/scanACol/config_BerCRS.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/BernoulliCRS.pt,String \ No newline at end of file +ptFile,torchscripts/BernoulliCRS.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/config_CPPCRS.csv b/benchmark/scripts/scanACol/config_CPPCRS.csv deleted file mode 100644 index a9b928d2..00000000 --- a/benchmark/scripts/scanACol/config_CPPCRS.csv +++ /dev/null @@ -1,8 +0,0 @@ -key,value,type -aRow,1000,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/CRS.pt,String -useCPP,1,U64 -cppAlgoTag,crs,String \ No newline at end of file diff --git a/benchmark/scripts/scanACol/config_CRS.csv b/benchmark/scripts/scanACol/config_CRS.csv index 620247f2..faf584f0 100644 --- a/benchmark/scripts/scanACol/config_CRS.csv +++ b/benchmark/scripts/scanACol/config_CRS.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/CRS.pt,String \ No newline at end of file +ptFile,torchscripts/CRS.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanAColCPP/config_CRS.csv b/benchmark/scripts/scanACol/config_CRSV2.csv similarity index 61% rename from benchmark/scripts/scanAColCPP/config_CRS.csv rename to benchmark/scripts/scanACol/config_CRSV2.csv index 620247f2..7d8585a0 100644 --- a/benchmark/scripts/scanAColCPP/config_CRS.csv +++ b/benchmark/scripts/scanACol/config_CRSV2.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/CRS.pt,String \ No newline at end of file +ptFile,torchscripts/CRSV2.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/config_CoAMM.csv b/benchmark/scripts/scanACol/config_CoAMM.csv index 765e54de..26aabc0e 100644 --- a/benchmark/scripts/scanACol/config_CoAMM.csv +++ b/benchmark/scripts/scanACol/config_CoAMM.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/CoOccurringFD.pt,String \ No newline at end of file +ptFile,torchscripts/CoOccurringFD.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/config_CounterSketch.csv b/benchmark/scripts/scanACol/config_CounterSketch.csv index 79eabd46..ad0ac1a4 100644 --- a/benchmark/scripts/scanACol/config_CounterSketch.csv +++ b/benchmark/scripts/scanACol/config_CounterSketch.csv @@ -4,3 +4,4 @@ aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 ptFile,torchscripts/CountSketch.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/config_EWS.csv b/benchmark/scripts/scanACol/config_EWS.csv index 0a752db9..f5834cbd 100644 --- a/benchmark/scripts/scanACol/config_EWS.csv +++ b/benchmark/scripts/scanACol/config_EWS.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/EWS.pt,String \ No newline at end of file +ptFile,torchscripts/EWS.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/config_RAWMM.csv b/benchmark/scripts/scanACol/config_RAWMM.csv index 57e126f7..78e00b13 100644 --- a/benchmark/scripts/scanACol/config_RAWMM.csv +++ b/benchmark/scripts/scanACol/config_RAWMM.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/RAWMM.pt,String \ No newline at end of file +ptFile,torchscripts/RAWMM.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanAColCPP/config_BCoAMM.csv b/benchmark/scripts/scanACol/config_TugOfWar.csv similarity index 59% rename from benchmark/scripts/scanAColCPP/config_BCoAMM.csv rename to benchmark/scripts/scanACol/config_TugOfWar.csv index aa481d3d..61ba7a68 100644 --- a/benchmark/scripts/scanAColCPP/config_BCoAMM.csv +++ b/benchmark/scripts/scanACol/config_TugOfWar.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/BetaCoOccurringFD.pt,String \ No newline at end of file +ptFile,torchscripts/TugOfWar.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/config_WCR.csv b/benchmark/scripts/scanACol/config_WCR.csv index a2b6b73c..83a349df 100644 --- a/benchmark/scripts/scanACol/config_WCR.csv +++ b/benchmark/scripts/scanACol/config_WCR.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/WeightedCR.pt,String \ No newline at end of file +ptFile,torchscripts/WeightedCR.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/drawTogether.py b/benchmark/scripts/scanACol/drawTogether.py index 2222a7b6..29e4d304 100755 --- a/benchmark/scripts/scanACol/drawTogether.py +++ b/benchmark/scripts/scanACol/drawTogether.py @@ -124,10 +124,10 @@ def main(): exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" commonBase = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/" figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag - methodTags = ["FD-AMM", "Co-AMM", "BCo-AMM", "Couter-sketch", "MM"] - resultPaths = ["fd", "co", "co", "cs", "mm"] - csvTemplates = ["config_FDAMM.csv", "config_CoAMM.csv", "config_BCoAMM.csv", "config_CounterSketch.csv", - "config_RAWMM.csv"] + methodTags = ["Co-AMM", "BCo-AMM", "Count-sketch", "Tug-of-War", "MM"] + resultPaths = ["co", "co", "cs", "tow", "mm"] + csvTemplates = ["config_CoAMM.csv", "config_BCoAMM.csv", "config_CounterSketch.csv", + "config_TugOfWar.csv", "config_RAWMM.csv"] valueVec = [100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000] valueVecDisp = np.array(valueVec) # run @@ -153,9 +153,10 @@ def main(): figPath + "/" + scanTag + "sketch_cacheMiss", True) # sampling - resultPaths = ["crs", "bcrs", "ews", "mm"] - csvTemplates = ["config_CRS.csv", "config_BerCRS.csv", "config_EWS.csv", "config_RAWMM.csv"] - methodTags = ["CRS", "Ber-CRS", "EWS", "MM"] + resultPaths = ["crs", "crsv2", "bcrs", "wcr", "ews", "mm"] + csvTemplates = ["config_CRS.csv", "config_CRSV2.csv", "config_BerCRS.csv", "config_WCR.csv", + "config_EWS.csv", "config_RAWMM.csv"] + methodTags = ["CRS", "CRSV2", "Ber-CRS", "Weighted-CR", "EWS", "MM"] elapsedTimeAll, cacheMissAll, periodAll = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, reRun) groupLine.DrawFigure(periodAll, elapsedTimeAll, diff --git a/benchmark/scripts/scanAColCPP/config_CPPBCOOFD.csv b/benchmark/scripts/scanAColCPP/config_CPPBCOOFD.csv new file mode 100644 index 00000000..d43c92f9 --- /dev/null +++ b/benchmark/scripts/scanAColCPP/config_CPPBCOOFD.csv @@ -0,0 +1,10 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/BetaCoOccurringFD.pt,String +useCPP,1,U64 +cppAlgoTag,bcooFD,String +threads,1,U64 +forceMP,1,U64 diff --git a/benchmark/scripts/scanAColCPP/config_CPPBCRS.csv b/benchmark/scripts/scanAColCPP/config_CPPBCRS.csv new file mode 100644 index 00000000..3b7ee42c --- /dev/null +++ b/benchmark/scripts/scanAColCPP/config_CPPBCRS.csv @@ -0,0 +1,10 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/BernoulliCRS.pt,String +useCPP,1,U64 +cppAlgoTag,bcrs,String +threads,1,U64 +forceMP,1,U64 diff --git a/benchmark/scripts/scanAColCPP/config_CPPCRSV2.csv b/benchmark/scripts/scanAColCPP/config_CPPCRSV2.csv new file mode 100644 index 00000000..b94e2d2f --- /dev/null +++ b/benchmark/scripts/scanAColCPP/config_CPPCRSV2.csv @@ -0,0 +1,10 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/CRSV2.pt,String +useCPP,1,U64 +cppAlgoTag,crsV2,String +threads,1,U64 +forceMP,1,U64 diff --git a/benchmark/scripts/scanAColCPP/config_CPPINT8.csv b/benchmark/scripts/scanAColCPP/config_CPPINT8.csv new file mode 100644 index 00000000..2b61c43e --- /dev/null +++ b/benchmark/scripts/scanAColCPP/config_CPPINT8.csv @@ -0,0 +1,10 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/FDAMM.pt,String +useCPP,1,U64 +cppAlgoTag,int8,String +threads,1,U64 +forceMP,1,U64 diff --git a/benchmark/scripts/scanAColCPP/config_CPPSMPPCA.csv b/benchmark/scripts/scanAColCPP/config_CPPSMPPCA.csv new file mode 100644 index 00000000..7c3a0223 --- /dev/null +++ b/benchmark/scripts/scanAColCPP/config_CPPSMPPCA.csv @@ -0,0 +1,9 @@ +key,value,type +aRow,10000,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +threads,1,U64 +ptFile,torchscripts/WeightedCR.pt,String +useCPP,1,U64 +cppAlgoTag,smp-pca,String \ No newline at end of file diff --git a/benchmark/scripts/scanAColCPP/config_CPPWeightedCR.csv b/benchmark/scripts/scanAColCPP/config_CPPWeightedCR.csv new file mode 100644 index 00000000..e92a7939 --- /dev/null +++ b/benchmark/scripts/scanAColCPP/config_CPPWeightedCR.csv @@ -0,0 +1,9 @@ +key,value,type +aRow,10000,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +threads,1,U64 +ptFile,torchscripts/WeightedCR.pt,String +useCPP,1,U64 +cppAlgoTag,weighted-cr,String \ No newline at end of file diff --git a/benchmark/scripts/scanAColCPP/config_CoAMM.csv b/benchmark/scripts/scanAColCPP/config_CoAMM.csv deleted file mode 100644 index 765e54de..00000000 --- a/benchmark/scripts/scanAColCPP/config_CoAMM.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,1000,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/CoOccurringFD.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanAColCPP/config_CounterSketch.csv b/benchmark/scripts/scanAColCPP/config_CounterSketch.csv deleted file mode 100644 index 79eabd46..00000000 --- a/benchmark/scripts/scanAColCPP/config_CounterSketch.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,1000,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/CountSketch.pt,String diff --git a/benchmark/scripts/scanAColCPP/config_EWS.csv b/benchmark/scripts/scanAColCPP/config_EWS.csv deleted file mode 100644 index 0a752db9..00000000 --- a/benchmark/scripts/scanAColCPP/config_EWS.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,1000,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/EWS.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanAColCPP/config_FDAMM.csv b/benchmark/scripts/scanAColCPP/config_FDAMM.csv deleted file mode 100644 index 2dac7db7..00000000 --- a/benchmark/scripts/scanAColCPP/config_FDAMM.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,1000,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/FDAMM.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanAColCPP/config_RAWMM.csv b/benchmark/scripts/scanAColCPP/config_RAWMM.csv deleted file mode 100644 index 57e126f7..00000000 --- a/benchmark/scripts/scanAColCPP/config_RAWMM.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,1000,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/RAWMM.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanAColCPP/config_WCR.csv b/benchmark/scripts/scanAColCPP/config_WCR.csv deleted file mode 100644 index a2b6b73c..00000000 --- a/benchmark/scripts/scanAColCPP/config_WCR.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,1000,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/WeightedCR.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanAColCPP/drawTogether.py b/benchmark/scripts/scanAColCPP/drawTogether.py index 20d8aa55..5cba8047 100755 --- a/benchmark/scripts/scanAColCPP/drawTogether.py +++ b/benchmark/scripts/scanAColCPP/drawTogether.py @@ -135,11 +135,11 @@ def main(): exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" commonBase = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/" figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag + "CPP" - methodTags = ["FD-AMM", "Co-AMM", "BCo-AMM", "Couter-sketch", "MM"] - resultPaths = ["fd", "co", "co", "cs", "mm"] - csvTemplates = ["config_FDAMM.csv", "config_CoAMM.csv", "config_BCoAMM.csv", "config_CounterSketch.csv", - "config_RAWMM.csv"] - valueVec = [100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000] + methodTags = ["Co-AMM", "BCo-AMM", "Count-sketch", "Tug-of-War", "SMP-PCA", "MM"] + resultPaths = ["co", "co", "cs", "tow", "smp-pca", "mm"] + csvTemplates = ["config_CPPCOFD.csv", "config_CPPBCOOFD.csv", "config_CPPCOUNTERSKETCH.csv", + "config_CPPTOW.csv", "config_CPPSMPPCA.csv", "config_CPPMM.csv"] + valueVec = [100, 200, 500, 1000, 5000, 10000, 20000, 50000] valueVecDisp = np.array(valueVec) # run reRun = 0 @@ -150,13 +150,37 @@ def main(): os.system("sudo rm -rf " + commonBase) os.system("sudo mkdir " + commonBase) reRun = 1 - + # skech + elapsedTimeAll, cacheMissAll, periodAll, fro, eb = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, + reRun) + groupLine.DrawFigure(periodAll, elapsedTimeAll, + methodTags, + "#elements in A's col", "elapsed time (ms)", 0, 1, + figPath + "/" + scanTag + "sketch_cpp_elapsedTime", + True) + groupLine.DrawFigureYnormal(periodAll, cacheMissAll, + methodTags, + "#elements in A's col", "cacheMiss (%)", 0, 1, + figPath + "/" + scanTag + "sketch_cpp_cacheMiss", + True) + groupLine.DrawFigureYnormal(periodAll, + fro * 100.0, + methodTags, + "#A's row", "normalized error %", 0, 100, figPath + "/" +scanTag + + "sketch_cpp_froError", + True) + groupLine.DrawFigureYnormal(periodAll, + eb * 100.0, + methodTags, + "#A's row", "error bound ratio %", 0, 100, figPath + "/" + scanTag + + "sketch_cpp_ebRatio", + True) # sampling - # sampling # resultPaths = ["crs", "bcrs", "ews", "mm","mm-cpp","crs-cpp"] - resultPaths = ["mm", "crs","ews","counterSketch","cofd","tow"] - csvTemplates = ["config_CPPMM.csv", "config_CPPCRS.csv","config_CPPEWS.csv","config_CPPCOUNTERSKETCH.csv","config_CPPCOFD.csv","config_CPPTOW.csv"] - methodTags = ["mm", "crs","ews","counterSketch","cofd","tow"] + resultPaths = ["crs", "crsv2", "bcrs", "wcr", "ews", "int8", "mm"] + csvTemplates = ["config_CPPCRS.csv", "config_CPPCRSV2.csv", "config_CPPBCRS.csv", "config_CPPWeightedCR.csv", + "config_CPPEWS.csv", "config_CPPINT8.csv", "config_CPPMM.csv"] + methodTags = ["CRS", "CRSV2", "Ber-CRS", "Weighted-CR", "EWS", "INT8", "MM"] # csvTemplates = ["config_CRS.csv", "config_BerCRS.csv", "config_EWS.csv", "config_RAWMM.csv","config_CPPMM.csv","config_CPPCRS.csv"] # methodTags = ["CRS", "Ber-CRS", "EWS",, "MM","MM_CPP","CRS_CPP"] elapsedTimeAll, cacheMissAll, periodAll,fro,eb = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, @@ -164,12 +188,12 @@ def main(): groupLine.DrawFigure(periodAll, elapsedTimeAll, methodTags, "#A's col", "elapsed time (ms)", 0, 1, - figPath + "/" + scanTag + "cpp_elapsedTime", + figPath + "/" + scanTag + "sampling_cpp_elapsedTime", True) groupLine.DrawFigureYnormal(periodAll, cacheMissAll, methodTags, "#A's col", "cacheMiss (%)", 0, 1, - figPath + "/" + scanTag + "cpp_cacheMiss", + figPath + "/" + scanTag + "sampling_cpp_cacheMiss", True) groupLine.DrawFigureYnormal(periodAll, fro * 100.0, diff --git a/benchmark/scripts/scanARow/config_BCoAMM.csv b/benchmark/scripts/scanARow/config_BCoAMM.csv index b65317af..2865329c 100644 --- a/benchmark/scripts/scanARow/config_BCoAMM.csv +++ b/benchmark/scripts/scanARow/config_BCoAMM.csv @@ -3,4 +3,5 @@ aRow,100,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/BetaCoOccurringFD.pt,String \ No newline at end of file +ptFile,torchscripts/BetaCoOccurringFD.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanARow/config_BerCRS.csv b/benchmark/scripts/scanARow/config_BerCRS.csv index d2b758a5..310d285c 100644 --- a/benchmark/scripts/scanARow/config_BerCRS.csv +++ b/benchmark/scripts/scanARow/config_BerCRS.csv @@ -3,4 +3,5 @@ aRow,100,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/BernoulliCRS.pt,String \ No newline at end of file +ptFile,torchscripts/BernoulliCRS.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanARow/config_CRS.csv b/benchmark/scripts/scanARow/config_CRS.csv index b6afe1ef..90915b42 100644 --- a/benchmark/scripts/scanARow/config_CRS.csv +++ b/benchmark/scripts/scanARow/config_CRS.csv @@ -3,4 +3,5 @@ aRow,100,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/CRS.pt,String \ No newline at end of file +ptFile,torchscripts/CRS.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanACol/config_FDAMM.csv b/benchmark/scripts/scanARow/config_CRSV2.csv similarity index 61% rename from benchmark/scripts/scanACol/config_FDAMM.csv rename to benchmark/scripts/scanARow/config_CRSV2.csv index 2dac7db7..7d8585a0 100644 --- a/benchmark/scripts/scanACol/config_FDAMM.csv +++ b/benchmark/scripts/scanARow/config_CRSV2.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/FDAMM.pt,String \ No newline at end of file +ptFile,torchscripts/CRSV2.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanARow/config_CoAMM.csv b/benchmark/scripts/scanARow/config_CoAMM.csv index f41d7ddd..7b6baf83 100644 --- a/benchmark/scripts/scanARow/config_CoAMM.csv +++ b/benchmark/scripts/scanARow/config_CoAMM.csv @@ -3,4 +3,5 @@ aRow,100,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/CoOccurringFD.pt,String \ No newline at end of file +ptFile,torchscripts/CoOccurringFD.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanARow/config_CounterSketch.csv b/benchmark/scripts/scanARow/config_CounterSketch.csv index 50cf2770..80d9bd4f 100644 --- a/benchmark/scripts/scanARow/config_CounterSketch.csv +++ b/benchmark/scripts/scanARow/config_CounterSketch.csv @@ -4,3 +4,4 @@ aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 ptFile,torchscripts/CountSketch.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanARow/config_EWS.csv b/benchmark/scripts/scanARow/config_EWS.csv index 8e09f17b..d1a15d00 100644 --- a/benchmark/scripts/scanARow/config_EWS.csv +++ b/benchmark/scripts/scanARow/config_EWS.csv @@ -3,4 +3,5 @@ aRow,100,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/EWS.pt,String \ No newline at end of file +ptFile,torchscripts/EWS.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanARow/config_FDAMM.csv b/benchmark/scripts/scanARow/config_FDAMM.csv deleted file mode 100644 index 18b9efde..00000000 --- a/benchmark/scripts/scanARow/config_FDAMM.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/FDAMM.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARow/config_RAWMM.csv b/benchmark/scripts/scanARow/config_RAWMM.csv index aeb092a8..8401fe58 100644 --- a/benchmark/scripts/scanARow/config_RAWMM.csv +++ b/benchmark/scripts/scanARow/config_RAWMM.csv @@ -3,4 +3,5 @@ aRow,100,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/RAWMM.pt,String \ No newline at end of file +ptFile,torchscripts/RAWMM.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanAColCPP/config_BerCRS.csv b/benchmark/scripts/scanARow/config_TugOfWar.csv similarity index 59% rename from benchmark/scripts/scanAColCPP/config_BerCRS.csv rename to benchmark/scripts/scanARow/config_TugOfWar.csv index 14a0cdc1..61ba7a68 100644 --- a/benchmark/scripts/scanAColCPP/config_BerCRS.csv +++ b/benchmark/scripts/scanARow/config_TugOfWar.csv @@ -3,4 +3,5 @@ aRow,1000,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/BernoulliCRS.pt,String \ No newline at end of file +ptFile,torchscripts/TugOfWar.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanARow/config_WCR.csv b/benchmark/scripts/scanARow/config_WCR.csv index d9b055fb..f02285a4 100644 --- a/benchmark/scripts/scanARow/config_WCR.csv +++ b/benchmark/scripts/scanARow/config_WCR.csv @@ -3,4 +3,5 @@ aRow,100,U64 aCol,1000,U64 bCol,500,U64 sketchDimension,25,U64 -ptFile,torchscripts/WeightedCR.pt,String \ No newline at end of file +ptFile,torchscripts/WeightedCR.pt,String +forceMP,1,U64 diff --git a/benchmark/scripts/scanARow/drawTogether.py b/benchmark/scripts/scanARow/drawTogether.py index 8078984b..9efed6fa 100755 --- a/benchmark/scripts/scanARow/drawTogether.py +++ b/benchmark/scripts/scanARow/drawTogether.py @@ -124,10 +124,10 @@ def main(): exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" commonBase = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/" figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag - methodTags = ["FD-AMM", "Co-AMM", "BCo-AMM", "Couter-sketch", "MM"] - resultPaths = ["fd", "co", "co", "cs", "mm"] - csvTemplates = ["config_FDAMM.csv", "config_CoAMM.csv", "config_BCoAMM.csv", "config_CounterSketch.csv", - "config_RAWMM.csv"] + methodTags = ["Co-AMM", "BCo-AMM", "Count-sketch", "Tug-of-War", "MM"] + resultPaths = ["co", "co", "cs", "tow", "mm"] + csvTemplates = ["config_CoAMM.csv", "config_BCoAMM.csv", "config_CounterSketch.csv", + "config_TugOfWar.csv", "config_RAWMM.csv"] valueVec = [100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000] valueVecDisp = np.array(valueVec) # run @@ -153,9 +153,10 @@ def main(): figPath + "/" + scanTag + "sketch_cacheMiss", True) # sampling - resultPaths = ["crs", "bcrs", "ews", "mm"] - csvTemplates = ["config_CRS.csv", "config_BerCRS.csv", "config_EWS.csv", "config_RAWMM.csv"] - methodTags = ["CRS", "Ber-CRS", "EWS", "MM"] + resultPaths = ["crs", "crsv2", "bcrs", "wcr", "ews", "mm"] + csvTemplates = ["config_CRS.csv", "config_CRSV2.csv", "config_BerCRS.csv", "config_WCR.csv", + "config_EWS.csv", "config_RAWMM.csv"] + methodTags = ["CRS", "CRSV2", "Ber-CRS", "Weighted-CR", "EWS", "MM"] elapsedTimeAll, cacheMissAll, periodAll = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, reRun) groupLine.DrawFigure(periodAll, elapsedTimeAll, diff --git a/benchmark/scripts/scanARowCPP/config_BCoAMM.csv b/benchmark/scripts/scanARowCPP/config_BCoAMM.csv deleted file mode 100644 index b65317af..00000000 --- a/benchmark/scripts/scanARowCPP/config_BCoAMM.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/BetaCoOccurringFD.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_BerCRS.csv b/benchmark/scripts/scanARowCPP/config_BerCRS.csv deleted file mode 100644 index d2b758a5..00000000 --- a/benchmark/scripts/scanARowCPP/config_BerCRS.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/BernoulliCRS.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_CPPBCOOFD.csv b/benchmark/scripts/scanARowCPP/config_CPPBCOOFD.csv new file mode 100644 index 00000000..d43c92f9 --- /dev/null +++ b/benchmark/scripts/scanARowCPP/config_CPPBCOOFD.csv @@ -0,0 +1,10 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/BetaCoOccurringFD.pt,String +useCPP,1,U64 +cppAlgoTag,bcooFD,String +threads,1,U64 +forceMP,1,U64 diff --git a/benchmark/scripts/scanARowCPP/config_CPPBCRS.csv b/benchmark/scripts/scanARowCPP/config_CPPBCRS.csv new file mode 100644 index 00000000..3b7ee42c --- /dev/null +++ b/benchmark/scripts/scanARowCPP/config_CPPBCRS.csv @@ -0,0 +1,10 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/BernoulliCRS.pt,String +useCPP,1,U64 +cppAlgoTag,bcrs,String +threads,1,U64 +forceMP,1,U64 diff --git a/benchmark/scripts/scanARowCPP/config_CPPCOUNTERSKETCH.csv b/benchmark/scripts/scanARowCPP/config_CPPCOUNTERSKETCH.csv index a06776ab..6823e4e2 100644 --- a/benchmark/scripts/scanARowCPP/config_CPPCOUNTERSKETCH.csv +++ b/benchmark/scripts/scanARowCPP/config_CPPCOUNTERSKETCH.csv @@ -7,4 +7,4 @@ ptFile,torchscripts/CRS.pt,String useCPP,1,U64 cppAlgoTag,countSketch,String threads,1,U64 -forceMP,1,U64 \ No newline at end of file +forceMP,1,U64 diff --git a/benchmark/scripts/scanARowCPP/config_CPPCRSV2.csv b/benchmark/scripts/scanARowCPP/config_CPPCRSV2.csv new file mode 100644 index 00000000..b94e2d2f --- /dev/null +++ b/benchmark/scripts/scanARowCPP/config_CPPCRSV2.csv @@ -0,0 +1,10 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/CRSV2.pt,String +useCPP,1,U64 +cppAlgoTag,crsV2,String +threads,1,U64 +forceMP,1,U64 diff --git a/benchmark/scripts/scanARowCPP/config_CPPINT8.csv b/benchmark/scripts/scanARowCPP/config_CPPINT8.csv new file mode 100644 index 00000000..2b61c43e --- /dev/null +++ b/benchmark/scripts/scanARowCPP/config_CPPINT8.csv @@ -0,0 +1,10 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/FDAMM.pt,String +useCPP,1,U64 +cppAlgoTag,int8,String +threads,1,U64 +forceMP,1,U64 diff --git a/benchmark/scripts/scanARowCPP/config_CPPSMPPCA.csv b/benchmark/scripts/scanARowCPP/config_CPPSMPPCA.csv new file mode 100644 index 00000000..7c3a0223 --- /dev/null +++ b/benchmark/scripts/scanARowCPP/config_CPPSMPPCA.csv @@ -0,0 +1,9 @@ +key,value,type +aRow,10000,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +threads,1,U64 +ptFile,torchscripts/WeightedCR.pt,String +useCPP,1,U64 +cppAlgoTag,smp-pca,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_CPPWeightedCR.csv b/benchmark/scripts/scanARowCPP/config_CPPWeightedCR.csv new file mode 100644 index 00000000..e92a7939 --- /dev/null +++ b/benchmark/scripts/scanARowCPP/config_CPPWeightedCR.csv @@ -0,0 +1,9 @@ +key,value,type +aRow,10000,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +threads,1,U64 +ptFile,torchscripts/WeightedCR.pt,String +useCPP,1,U64 +cppAlgoTag,weighted-cr,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_CRS.csv b/benchmark/scripts/scanARowCPP/config_CRS.csv deleted file mode 100644 index b6afe1ef..00000000 --- a/benchmark/scripts/scanARowCPP/config_CRS.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/CRS.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_CoAMM.csv b/benchmark/scripts/scanARowCPP/config_CoAMM.csv deleted file mode 100644 index f41d7ddd..00000000 --- a/benchmark/scripts/scanARowCPP/config_CoAMM.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/CoOccurringFD.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_CounterSketch.csv b/benchmark/scripts/scanARowCPP/config_CounterSketch.csv deleted file mode 100644 index 50cf2770..00000000 --- a/benchmark/scripts/scanARowCPP/config_CounterSketch.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/CountSketch.pt,String diff --git a/benchmark/scripts/scanARowCPP/config_EWS.csv b/benchmark/scripts/scanARowCPP/config_EWS.csv deleted file mode 100644 index 8e09f17b..00000000 --- a/benchmark/scripts/scanARowCPP/config_EWS.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/EWS.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_FDAMM.csv b/benchmark/scripts/scanARowCPP/config_FDAMM.csv deleted file mode 100644 index 18b9efde..00000000 --- a/benchmark/scripts/scanARowCPP/config_FDAMM.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/FDAMM.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_RAWMM.csv b/benchmark/scripts/scanARowCPP/config_RAWMM.csv deleted file mode 100644 index aeb092a8..00000000 --- a/benchmark/scripts/scanARowCPP/config_RAWMM.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/RAWMM.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/config_WCR.csv b/benchmark/scripts/scanARowCPP/config_WCR.csv deleted file mode 100644 index d9b055fb..00000000 --- a/benchmark/scripts/scanARowCPP/config_WCR.csv +++ /dev/null @@ -1,6 +0,0 @@ -key,value,type -aRow,100,U64 -aCol,1000,U64 -bCol,500,U64 -sketchDimension,25,U64 -ptFile,torchscripts/WeightedCR.pt,String \ No newline at end of file diff --git a/benchmark/scripts/scanARowCPP/drawTogether.py b/benchmark/scripts/scanARowCPP/drawTogether.py index c67ec677..edcb416a 100755 --- a/benchmark/scripts/scanARowCPP/drawTogether.py +++ b/benchmark/scripts/scanARowCPP/drawTogether.py @@ -135,10 +135,10 @@ def main(): exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" commonBase = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/" figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag + "CPP" - methodTags = ["FD-AMM", "Co-AMM", "BCo-AMM", "Couter-sketch", "MM"] - resultPaths = ["fd", "co", "co", "cs", "mm"] - csvTemplates = ["config_FDAMM.csv", "config_CoAMM.csv", "config_BCoAMM.csv", "config_CounterSketch.csv", - "config_RAWMM.csv"] + methodTags = ["Co-AMM", "BCo-AMM", "Count-sketch", "Tug-of-War", "SMP-PCA", "MM"] + resultPaths = ["co", "co", "cs", "tow", "smp-pca", "mm"] + csvTemplates = ["config_CPPCOFD.csv", "config_CPPBCOOFD.csv", "config_CPPCOUNTERSKETCH.csv", + "config_CPPTOW.csv", "config_CPPSMPPCA.csv", "config_CPPMM.csv"] valueVec = [100, 200, 500, 1000, 5000, 10000, 20000, 50000, 100000] valueVecDisp = np.array(valueVec) # run @@ -151,12 +151,37 @@ def main(): os.system("sudo mkdir " + commonBase) reRun = 1 # skech + elapsedTimeAll, cacheMissAll, periodAll, fro, eb = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, + reRun) + groupLine.DrawFigure(periodAll, elapsedTimeAll, + methodTags, + "#elements in A's row", "elapsed time (ms)", 0, 1, + figPath + "/" + scanTag + "sketch_cpp_elapsedTime", + True) + groupLine.DrawFigureYnormal(periodAll, cacheMissAll, + methodTags, + "#elements in A's row", "cacheMiss (%)", 0, 1, + figPath + "/" + scanTag + "sketch_cpp_cacheMiss", + True) + groupLine.DrawFigureYnormal(periodAll, + fro * 100.0, + methodTags, + "#A's row", "normalized error %", 0, 100, figPath + "/" +scanTag + + "sketch_cpp_froError", + True) + groupLine.DrawFigureYnormal(periodAll, + eb * 100.0, + methodTags, + "#A's row", "error bound ratio %", 0, 100, figPath + "/" + scanTag + + "sketch_cpp_ebRatio", + True) # sampling # resultPaths = ["crs", "bcrs", "ews", "mm","mm-cpp","crs-cpp"] - resultPaths = ["mm", "crs","ews","counterSketch","cofd","tow"] - csvTemplates = ["config_CPPMM.csv", "config_CPPCRS.csv","config_CPPEWS.csv","config_CPPCOUNTERSKETCH.csv","config_CPPCOFD.csv","config_CPPTOW.csv"] - methodTags = ["mm", "crs","ews","counterSketch","cofd","tow"] + resultPaths = ["crs", "crsv2", "bcrs", "wcr", "ews", "int8", "mm"] + csvTemplates = ["config_CPPCRS.csv", "config_CPPCRSV2.csv", "config_CPPBCRS.csv", "config_CPPWeightedCR.csv", + "config_CPPEWS.csv", "config_CPPINT8.csv", "config_CPPMM.csv"] + methodTags = ["CRS", "CRSV2", "Ber-CRS", "Weighted-CR", "EWS", "INT8", "MM"] # csvTemplates = ["config_CRS.csv", "config_BerCRS.csv", "config_EWS.csv", "config_RAWMM.csv","config_CPPMM.csv","config_CPPCRS.csv"] # methodTags = ["CRS", "Ber-CRS", "EWS",, "MM","MM_CPP","CRS_CPP"] elapsedTimeAll, cacheMissAll, periodAll,fro,eb = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, @@ -164,22 +189,24 @@ def main(): groupLine.DrawFigure(periodAll, elapsedTimeAll, methodTags, "#A's row", "elapsed time (ms)", 0, 1, - figPath + "/" + scanTag + "cpp_elapsedTime", + figPath + "/" + scanTag + "sampling_cpp_elapsedTime", True) groupLine.DrawFigureYnormal(periodAll, cacheMissAll, methodTags, "#A's row", "cacheMiss (%)", 0, 100, - figPath + "/" + scanTag + "cpp_cacheMiss", + figPath + "/" + scanTag + "sampling_cpp_cacheMiss", True) groupLine.DrawFigureYnormal(periodAll, fro * 100.0, methodTags, - "#A's row", "normalized error %", 0, 100, figPath + "/" +scanTag + "_froError", + "#A's row", "normalized error %", 0, 100, figPath + "/" +scanTag + + "sampling_cpp_froError", True) groupLine.DrawFigureYnormal(periodAll, eb * 100.0, methodTags, - "#A's row", "error bound ratio %", 0, 100, figPath + "/" + scanTag + "_ebRatio", + "#A's row", "error bound ratio %", 0, 100, figPath + "/" + scanTag + + "sampling_cpp_ebRatio", True) # draw2yLine("watermark time (ms)",singleValueVecDisp,lat95Vec,errVec,"95% Latency (ms)","Error","ms","",figPath+"wm_lat") # draw2yLine("watermark time (ms)",singleValueVecDisp,thrVec,errVec,"Throughput (KTp/s)","Error","KTp/s","",figPath+"wm_thr") diff --git a/figures/aCol/aColsampling_cacheMiss.pdf b/figures/aCol/aColsampling_cacheMiss.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c8dcb49eb6040e77e888e202030705ca114d7234 GIT binary patch literal 9810 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 LKuAbkPXq8j_N)Q~ literal 0 HcmV?d00001 diff --git a/figures/aCol/aColsampling_elapsedTime.pdf b/figures/aCol/aColsampling_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..49c2519de4280294c0780ef842eb6b996d55a2ea GIT binary patch literal 9913 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 Js*W1ye*gnFPH6xD literal 0 HcmV?d00001 diff --git a/figures/aCol/aColsketch_elapsedTime.pdf b/figures/aCol/aColsketch_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..bbe20ede116f868bac072c94e9b116fff400be86 GIT binary patch literal 9612 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 literal 0 HcmV?d00001 diff --git a/figures/aColCPP/aCol_ebRatio.pdf b/figures/aColCPP/aCol_ebRatio.pdf new file mode 100644 index 0000000000000000000000000000000000000000..af7b36e05d5ed2e3c270211008ba17e161f3bb53 GIT binary patch literal 9922 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 Tq}>#hfuj&00Rc4~H0b{UbXrBL literal 0 HcmV?d00001 diff --git a/figures/aColCPP/aCol_froError.pdf b/figures/aColCPP/aCol_froError.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b8e87b8e9a02900dedfe81e2515ac725f91d2002 GIT binary patch literal 10018 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 literal 0 HcmV?d00001 diff --git a/figures/aColCPP/aColsampling_cpp_elapsedTime.pdf b/figures/aColCPP/aColsampling_cpp_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a6bf4ec5f08b4c4b435a080cccb42330b23449d2 GIT binary patch literal 10094 zcmch72Uyd~vo;+Kh)NTb5>c9zkOV@42vVhm-kSsn9YP686O^KK1OWjl3Wy>dq*v)8 zMFpjUl%Oaey$fH0dc@T`?9~ zXe`hOuU1wb4+ZUk1%ebE@erhcyvqD|RRo$Gf&>2300M3TdRH_a-FNsPO|%=v-PHnb z4*@@3KN4+ei;~88;57>2e__He6rWPx2cIM0*L2dNR>9kTyGoiw;r`v9`%?SUOPN8&7NU3VD`)#arka<7h>Ta*@L4 zPj_P$a2w_Op5AUdlY=_@qpuchOqiD`TY{q$lf!N<>S+{8rrVe8f$ zB4}^h{rXnMmyqo*SF5?NR$_MSEh%r^x4ehGLQL^!b(-&@FYeeNy@@MxM#++}PeNyf z*{)46#XNg{bz1e=)JOpHmzs0+&5z`&UDP?~WJ6?%ajz&Fzg+gYkR{8WVnp&Lee|-= z^VYB!ByVriWw`9N56Xj8KF}JGFh@mcn66GMDSb+cUO#wFIYops+m7aioLaJ-=5qyJ zMp%ejtF~aMk~YIjPMPWCV+iD`eX0yoS!-IL>q$jbM^Ya z;iCHP#kF)c*Cwoz9{2gS`XK6C*VpUCb>6vOH)@~B5kGX<3{F~`DD!)_pYvqzNo7NV znMnxjmZXOL&}qbgbF7qA5CSBJ4EZqfYT@JFHybAlSuU9z;^Tw0)EN!oJT^pyxy|*N z3W~t}`sTRveIFC-C!g6sUA&qTDy$k*Cn4J>^;oo)cJKGaP$W$D2YD#a)ZU4e?yLN= z^Qb7Me`M_2$~Zgb>V{uUZT-BTr|bUGeT;RV#D#C-=j(6E0V*iwf-c{uj1^G~aO2(X ztJm)db4t>L1UWQ&IXsIkd82>f+RbMd&OUrcdt?MOIaF*}5z}s7G-jJlPkUQShVJ1u zNvC$lS@Ji!#Oyt`p5JwhuR1q>R1@MRB87~B>#N<= z_1hX*AK$NgO4)qZ)tsncRe!qMN|lYF%aMmWD!rX?#A>36d;-a9aOcE)_B<8Yy}VMO zXWN+$kBk?qkAa+;B;g^H=nm_w2@#Jc5AVO=Pp#CTMoX8NO~sGGr0o|avtoxf*%YDY zx`_iVWx8)BUB>QqN>#o7@T%eR7TL#e--j*m5$eWlzTk`}GClt9#-v%?LLc5xsB3{2 z-;P9jq?1?5wB}CD>G8Bp1AECo*|?}K#;My1*gyPAHYR$@k7)zr6!&bwrkQx)j><7Q z+_jTLEQXnaa=Z=4-Hpg@k`yt%?%gK3AYL?gc@yEPN~0>-XL8nO;3C(@2~X!ISpf}< z_EL;1*{Qm8^ z$8ZcI#L(GN|1KUT>#|#BB#BfA2EWh2(7^j}B?(8~aVsH4|g zJ~mjc++GgdzZ@?c-O%D=#T+}&u}m)SdZvo6J%C@S5wa$0WtybF*Ns^L# zZ%i`z_9^Nl(>@YmDpOuR+L0CGPy;ru4gk5EVyP1Q6f1jCsz8Ca``yHh1igrG(ijxe zP8!3AlvskH7twY8<9$cSwofdKK|D>HSg$#>&Nv*qPK|8ve&alTv>wxlSv0+Zy>gC* zNb=(=F_mdJX76cvROy<`$?c4KSwrub|AD@9P7^+N853GA!(WudjYr=Q_f;g zI^RxRW~=YBpwe%U-6q#ilo+WK_=&`vr0da{NTr>7m&YCYe4G?~CE#%4+B55W+V7uU zX$fU~pltdm_3=5Ln0AJj7GFX~IrA1%2 z-Q{{Z-|@iln{|UZ3sG>QZ^@wWPP(B+VhEM#N#!CpcJ}p?x7hkKC_Bg-B%$G*6?4$4 zJ(ltseGAj4XIQy2q$JBDEZYl>;mPtxm@-%`JyOf53xv{$&N=fw>UUS#@%w5o&GPXz zN^Eo>k>nD$w~jMa4Xi5V$GR4Nj6P0 zrK3BNxnF#&wn-9S4p81YJ2H~oM%td?ze!#G#)I*?m2vEwKG{|CJ#FS*nq6}a4elO` z=1l7W`C~;xUrsJJDSmZ5UhPtIF|EH`ukvz0-Dd68tGkms0Y;Ns!-_ZTS8-Zw1tESh zUp`l&5(En_lE@HI1?HY-13@fj`AHfsLgM4*_8HHXK{He-sz{)q7#qr<2Trs%GpUhQ z^2ByDp{4p-x23EChE|uimaMK}7|q@oVojHoOam>ao|fpRa`wJLSf8Q-dl$^v$#}WAf>6=abN0;kCeN84$VQo51HC=Zg$o2_ zv>1|EJe;bK0`@1!jB4FhI6ch4_Nl*P!k}|m&#L%FZ0uz)AiJqr#AU6s^j=@+0xNH1(Z`_FN`h(xBgKc_((aneqol!XJ;7clsv{ z%Po?tGFx+-8+<}{2y{Uuto<0pCE~y!U~Sbm=c1#1Z7iIZ+HvX%!fF|wHnxc}V-vGI z?$<=Bg`(+wVmhws!F*z5_yyoS=dV z`=>oBJ-RAyLNV|okNr^=93;JjL>M9}jQCkA9AwJ`p%KvJrwl^Kpnqn}-z$!TG6JOK zZjL=DKnOxG5G0LqLw|pwfOfcs#@bq-03bOhd>T!t8$f!tPEt;8wtoqJRVWZbiSbjz z_naII6o%mygMMV_P%spM&&&TMKYyp|ZLHm&vY)b3Ykiy8s)Cd>lp3zkDjFKF2>>ey zNeC&C37kKRw)Bw2odwDt^JMC4ZGH$&Y__%)es3;{*2+1bHF!QL>wV#{cISGugB@qc zV2tp*<~+xxxvw-f$n}!p(faLKgj>&UUH!_%`hLX5uHaFQ&>1Q2o|@#!axLn?;AYvG z)~;7ZF=@ROHUd*Dt*M?{uZr7Ps@CYIh^9WUx&dZ}osbx-k)F-vnBA9k?@;3pkeO=` zQ&U4+!DBKFr9ioGD&;e0#IaW=Ra)WP*RJp>pyH;w6Q;ipIjb_N{ zzyCFb)wFw)&2&W@ohW%icXx)7WB8P~WL^yOI>zuzaAO;!F1z^Igzq^X36#T-TR}eW zT38fOYh1XA&fbpwn*6KNt;Z9Vw0CkkT79m)$_d{nk~Aq5Svy9`Z3B9ckK4*Fbw`(q z8u?+W8uwl*LEIP=1CSPE0IH=i=TOrQKtGfI9}_4VnQ=XRhsR)(*VwI*{tRFu(UsBQo5qG?^RFc_@-?%PD= zRjO=_0-lE!xfWT@A&I(F)g}6pS)g|pSJhTklk)q&qfzn}IRJ&g* zd_KXhd8yW4Ejm(fjb&7dJ)O>R^`sFP>K4c-@Rpa#AY;R$9%84swbD5V$>^m#p}p7bN!kCA3< z-aTcyfvvKc9V?Ia$S*a=Q+>MoxM{LDtB?U|ai@j%jm4l`9+qaq?3gbn>k(Pk98*j=hCXT4Hdpz(*Q4c|VNtfqh;&!4xHNah0E;RE zhgOTZY{UbFl=nf~mZm+YbCE0}8pj|uoLXmQ<-9^PPi8W{rw{Fin3&GQ?W|II?CD~DD^`B~j^|d8N>cD(XW9e0 zBxppLGH9PM_PMtb-=*PjN8XY$W^{>WS4qy&wL_v?*dQbu5+F61%a^l=dV;@7Ox^H2hs6Ns$IZnOSu6Y zjc&2Z(CIhCozt}|4T^YPA$3kJ@J-w>n~wS>gvz>$=QCoohX%Q@w6>02%XFa$l@GDd z2!2~SIr~yIaRPartBs4VNPV6WEqRh^=XmMt+RDY5jTDRpdCk>r>Bs>jWpQhBltP1Z zxz^|DSj`?-9nNQH?DJ6einp?S1y|!}6SY2V#NNpIfd9yPg@3i%unGC~5^g4s8}e^v z^Hck;UYGA-SZYeKI#a+(`7kc?DJ|B=UV9=P$vcBa)>BjHexM^`Y`V< zs-A(K58e)>*x(wXt+#E?3PdiP!=8U(pwePW!(nk6nI-_qid1Dr7g=>O&PrT*k1jF{ zE{GA`KIL+{_uF+J?^pdjqxFw+7Gs>dYA>3um6ev}(OtCGxm0atBD7O>J!@02*0YDI zG~{zR%QuO!uU?V9{O_!g=>rLi0%g%g;^4fZb=_gXuahw^q#7Txat?819y-?(g`8?8I?Ki58MxPEz)&putI&zdmdt$ zd9l|*E19=@np!`WOZ&E%-(F|h*SN90uupSplIezWFS8$Yq%+Jfj4>~4dTGzF+gj>B z{ZO;>Fk@$EKW=0D6e85&E0lUic?-9btHeo*=)(&au=F=7A+Gnlte*--zi;iC>SSsa z`9xBGa;MYB1T*+Nb?>}x81(Eh82xLqXVcql1!VIufzL&TBdYL9Dd}+1ZY(%af7pTq8kqGSAtPk%OUS=|T zxws$j&bB{~vGB2c8Co~eE*|!6aV2R#t%W5^cex6;8}R|99H;VNs6(1>_fhcXgJe&( zbq9fA)2^qn8aL;4ivkfFI+wQ23arg(9NW<86v=yE;(%1R7v=awtM$IFiBZNeHve0c zGUN99wS&^u$f?oLiRDwuF2cDo-f;U5&!p3+_Geqtd@5+0(Uf~nU*{~co9@22HBPw{ zbgF(Bc4bd>Vg)EcmHy;-{d`kBpN|;T{oE9kht$JGhFH=AfWUl&?QJ&&lCar?%te9vVcx~iFpksjJ0gQjrIUZZ4aG^ z%tk)dnwl2AtGb`yE}GYPlHsQOYRSzZch;sP7dxg}3`pUrkM|qGECA!jCpm-sv~Bb@ zQyasGcLPYrFMW<1KlZ`K=(+f3IV0h^CRM*D$FI=WJ$dpfdZ)CbJOH#ztD*w3OUfB3139d)B56TJtFpm^y~L zs}|KFNSXS%shgD>ry9g6(Bj&rIOm~{@qEi?6#6FSvE*#awIFV`wDW1|9zL{XE(yak zABr%t?QO=J@?>QY3wt6XxRz1Pz?^JJW5$EzWsM-Ds(AWhVWSMdfb=*_kCGvJwRs*UE+tuUGp3`%cwHt4(4=jZ6o|d(qs5V_hEgJX%XOt)_#)R8GtFm6RmfetCRui_@Qse6 z#Nq6x1lqj8f~PIoJa7XDrl}SiOdty@Ifl$hQ$d4?A;>Zkia4E0B)@((L`DGsd_yB@ z{W|aN>pLe0gRM^#2#McBC1;}mE;T%YY()UUAf_N2#$a7%*W7LgCS)+6;gMNX_`PdE z3h|NQGJ(<+#1EvI!h(49O$x~#u4Hy|0~tGmCP63}yX+Gb3R2kMhM9Tu#&Ma9`cl$; zd*xlwLwha%KdU4NfeiV*Gyy{Jwa&klA{J&3!Dc8kw3&sO^#>v%qB$b=f9RY*z5Km% zsK~$fZlZq4zDelB=o+7s%AJP;vo>U$CgQ6BVu?x=24c)o0wE>ho8x*hbfT*tu;QcM zZBt8HJ40e;Zu!ONvC0d*w{3jclX=36CD%gd*w8Z%8JtcAbvU<6xys45_sl&>6q|a6 zs?m%CwKn5ZbfiRkQm0>55nsEnRqpHVc0>}M9_DN&eN+BkckRnX!7F5@%{#hJY9n4r zyxe2@$O-Ht*URC=iKt3lI6q5a*>yJVW@{!bb;@3OeYRK0o2bOp){>iFDfRO*Oxu>a zD`y^Dcb7;j8K}ugF8S6gQ+#+48v1l9?p z2Za3K%kZkSF;^62ktk>2K~Np$q#y)J?!PsPU=6+;{#9cCgEfCu)}WtA1r&fF0xEpT zk8;8iFuLLCGst(k3(uKpV|1Ks4`?pPcNXwaP5viM_ct34Y*s}%;;Fkoz#MRB)^0#3 zb?IaxcP@vZ}D;m1&y@P>d9KR59se{iUP9|9!GL(kR{&+@_W z{T;H8FfIg_8v%vkc&8Aa{{7G7*CEK^0g}ge{+(3>$%BChV|REk53d+f;Df089;d$; zR*;Mo0jvcI2tJ4&Dae1>48PX=Y6kr;n+XZR4;m6)B_s~ndFW{6m+?Ps$4C4x;o-#y zDFg)npox)SAedkh!Icmo_<#+@zr~N>kH|*i$MFY;j1&Qaf6}!uAox2I`%A+?m%oSk zPZIjqVUj$?)e#?2KLZ9VC;}7!6aN4DX9D} zwm%b+i_3Un2N}Jw=77lphY(-2}`aNBVt(ZJ-U$6;nx&MpWSVxlsO zBS-!L?4juX9|HRyY{@^sl9)p;X$2Vznw%i#a;>=g!>eUa{t@Wm8TWmO_-C&IeoY4< zK^O!9hKYb7!myw7;y2mBEWt0SKMqb|_+|4yjR_K3E3Yg-rEyi3mz8|{ZL2ImtCxHh z0HHuqC3KRM+~n>giy$>Gw(EPOg~9<l+HvD@#C+q!Yi(5D@sGal^Wz@QI)6!NoW&TQ4*| quJHLh21A$%2kFZ}l7BE24$?I@EXoyo5P}F{s0e_QQ%+4D@c#gRHpK#kzu(HbVC9im6c!B>_%2XIVXA*LnH5S3L07x3A8t#23ApAQ(Nqc(??hb-4eAFEH z$3N|N9c^!cwFKg-!IuHaS=r(=#$9c3W{^RfV$9HZ;7(XaG|CR(l2EJHVLu{A-5Ga7 z(ilu{aXzOyCt0a2mj0wMFpStN3gI9hGZ$&w@7Pi&k+u1if7$2(HC3CxZLyBwEYh=z z1(A4w-K(Pv`1aArupIPJ=*!x?!^i&h3tskm@4cG3H+stp7oFbI5041eH}mT?tl2#` zFE(tb<#HzBJZ^u8Lbby~!7L-AsZ3|}Q! z+87?cC_t6qPX*?Ac5KD?Ms^OnSOhHrG=ZtM!#Vq5dd|Qn(J#!cGgN%)_u;oj<9*k7 z?kj50p4#aE>re1pd#Jz-pfvcb!Dk(*zDm)@fXunCn0`h&qEk8DC|^eLv~QC)r&ggB zTgGFPfFii&hNYUO@5W^dgXL^4+#A_mV8u$Hd}~1% zGUjS=irtCr_3ioX_Z2(qjalpCH#X+RR`O>z=yvv$E_W!f2owWh$ep#Sz1qDV^_`A~ z#=he4$B&<}8kMaWJdf&&tLThh?=ZH^j+e41onfLmb>9z7Y(c0rr_fL7#@9RtI z_>AOTCELi7yk2!7FxBli5n8N0Tgm+HT?g7E3LhnA4ssK!yp+eKobdOU7%E!0|FGS?jkoX2(ULXO| z%g{vVIz(KWxIRN3(S70=J!HH9WQG1T*4?=Ct&eqnVMxMgcO{&ab((D6FfvgX&LFo> zAm2_7AkCc3YntfaFJFDYua1uLeVCuzcd9pqq&U(CjO4g!bMl%X5olj6BUP|q<+Fzh zL3CaoipV`cm48|9F^bIGSbZ@fH{@=@z?LsN&n=D0axla3UXKum%rA|A-CHCFxf=7P zodt3N`WIRh)ncA)-!H3U8h;^O-=9<`G^dgrTt%69!tvJZC%#HPxXQiRQy&8PA_n?> zb?*u!cEnO&RUfU0kDTpyBjFBr<~tc88WvmN_+V)JIYcw#ho6NNYgw^sd+3xh+(@>n$=MEhPJc^RlmG>im(J3}`nZmRTn!je@j z@I<9$y@zGm`o_#|O4>|jWq5o`4-q ziJS5%SL9C&CcZJEx`5@s7DJAFb3-^Z?t=UCQgt#G9#&b;)n!k5lVVi2$iu{vi@H_^ zwMm0F4AL1qH^+5Er&x-e67aZTDQemzt@LMfu{xTZZvdBQNbBZkTZJz@@GJ06sb_F=(HAA>`d_t?sec0uD#);B~(?`IVYg3ISwA3a4H81!CNpGjj|3Jwep0-iIgc)GfiMh@=f z`lYk=8%h)=|N_VtYnXWjlc8MsxN&_%Ru{Q$lguvq$a?NPNP!g{}`% zde@dqi6E3y<4et=s{eqk8em~Swu}ZUlwz6`r&ZUyOLl@JxzAisQKkT%Z- zX3mV3Mr9~>n$_>!<+4&YZiPr&7>nyJ~E7q0+EZ z{q2v6^qsq(=J@C!{TckwmRZ`Aw*#ORWBcWiS55%hc1R*WXGlJw&u4=T($BXBja-t9 zttr0DX5cajWQ_o2QNHSNU!GWhZdmPU&ly{C=blE`_^o0&QmT?SR$WBh4jP%}_j-h` zcciAz3@u2?IFvQcpX~2rc=TCyOY;8YO9~knz~@~S=Y>&u-TRiorJRG6GAB*nwq(wJ zq@MI`zsNCN-~LkarFuQl^n-`o^D6wN5&_#La>snBcppJuT#pKs&-k(fKO?|4`!>Xu z!5-4ZE+g4fEZa!*nV9o^ufGGg#c2Zgo&1}YMBbG$D%6)q!D;E^eBR>^tQD&ZUbxJE z6-CtY5+ihL2e!j%g!V8t!@S~wkvus99;e;6wr0oIzD;A@H<$`X#9Mjvftf)za-=&!oRUqocX@k2EwoEN^#Kh$##f;>)E z^45FEpShE`8!Lw7gtpK>B<_z!)0mhm%)si)VGJWPX3xNDg(@Gr<`3NW<`(z+(XWYMK9n5Xy}H6!%V{RKS0i^oS5G){%6_{(QTxtFf~VK*^_}D! z;fY%*<@2xNDW*kaWL35j2{|Gd#kz>QdlX_~LuRA0&+|XoXmvU@)2OQ!eGS{?W9xmD z(9TfG5cOuoD&rDQOL<>oTOn05L+!^G`)jj(kIuFRFQtf^dO|W43?i=ItKe->WA_^D z%2YNBX`-Ml487DPdS)6{Pnf7nhzWg;i8~++4v~iAL-HTd<~YHo+dI0eB$<2$DiMp}#*-K-=CzW35b40FbObE||qf z?;vd}dr5mItG@)l@&qV8?*Dsa3;_xVLBT-Kk2o0yfx-VhO8%hbZlKYZc#ybLYvF&) zypoXcKADI@i|~D)O#nmzEDlyA;$uILHgl1gJP(v3cct%XX-a{_Hd$B+^qL5xk-6-d z1MG2`z0Za;Uav>mT5|*qJP?>upJTf+yFg)yST7kGsoS20J9Y2As9U*Q*9YI&e&HWvlHMtJP7Rtv<8auh|EgrWzazi$XBn-<0 z*T@MuEkW@GlUvzk&ge2>{X3YdhW$20s1xlqAA~6pfOP3KXTtEqrl2ZMwPQ}sNHb$& zgwTJ<$d&t|2cA6!Gld0Tii-2XTGyO&v!AEt`A^@kD%R{V zm@YJrZ7-&Mtvgw`j$E<66WYpjPDeVr?#Y9=TxI4|+wB(G?%5i=L*{{<4!)wITb~G!(r&E8Fjin9!SRfv!EwCMT|iK@8{39}8@T-^p;~ixZU5xeGRY zzxs{GU(aZ3m;kNDh$yRks5D!o6%@?DP9k0tqfK_jJ~g8Gx*VJD)*dvfb)*R?eK}GH z41ObMhFUauUPx@y73Vm`7%9n&joCTZBe&CplG{~&!#GuH4SH*?*O7o6&vUu1gdRn0 zdv_Im))EaC5~_%J7pt^NnypsIm13G_n&}V}t3_H}q9c(B`fzzwWmP$@pzm9vTaXdx z-BOJKKjjLH26I!n>y5$;6|4G{T5pxeFzq#_5lPlm8oSlg`Vg3NjNVr&JF^=Gss1eQ zgshcfSITG8uMFF`yg)Khed({(Zc4)@CHWL|W)Y5ywK~V}zfa?O!!o{_VKX^Wb?5U z8^+{b975l?w@-VDmywwhaP%}(Z9KN&oiw@9YQG+udCM-*h;8sIvbL$p+qn)c*CZ5f zr36oPbc;@Qrt>ka(zR_doy~^FDZjA`de7YN zgBlu5MenSVGC2kJ7Z_$Le|{r!sZZjIK~ykCHM7llvBXf)XW#2|0k{-PO?AH_Y+|@5>U81{_;hks& zdw}bf-}Sh_f!E3LG;y%dawX6K-NRCMMV>1|A$Hs)u3H}+r zn#-pJLez^*c=O-(Fg}NE2aO5c)}S6PI@K7upER1pZHC=gr%%obQj2>ZsJtP2ncOZU zJb@%51S&tb02OTS5RUoOa0E%060_;j0c>=@$q#ny{FMXGajXo=ILJCtS9Yb%$hHWD$W#5Fgz zrNa6VCyHB|!WCXRR3K+QKUD7)dNJuSI65)UAI&^<{z2AFyz0$kd zX~>ZHb_plFi>KV%>4K!b8@J`UnU*t!KZkyZNYokHQluMm0om_USQz^;q9|G8Q<^S_Hgg$>mI3llDqi8p|kd~(OP*~Sw78W3(YIl z#)jaX^4po4{I#y#q-8-f6-;~LqYG|fUc4X75vl!;7x~H~^~E6hMeABa{K3^9N_fy& zlR^DH6XU}WBJCRY(pHB?!FT2i78lPKeA3%3SKUpxJIWIF0A{?3-MF$%Fr(tZEx3%NqQObBx*5t@Xs6MK=}160v?)aM z1v?gL*}gPKeaSBkGE2Yw-V~X@-SwGF=ix;Sf6+Vpuag&|NB4uj&ZdCfcKWR^; zotqzJnBR2Mm}0du(|P)-W+x?WXYe3;WBV-pzU=~xY)5HpawkubgBsq06V7ALcs_?Z zM!8u$<&W%b>7IB^-y-<+c-`rp*B*wLfzqUXcCBF8d2*pMZ-{a}Z?_f_%?a_%6zL7W z5q=oWBdV=BvU?Fh`avs-?o6v?#MF@7u(-?w$qO$+KC4O{F&X_z(dhSf9;|)Etj-Ca z0Og}EKe+NnFL!=B&#FBtP!P*f0R86r+B}xzMd&%5s*qg`S(@1DyE(dE)JP{w!P}I4 zwFSB2zU`ZJA$MD7HP-QXh>|`kUJ7bx75C^#1W5o= zg(Hu)};8CurY38}1^;P7i`Yo;m5hGregr=Z?wF!yE_K9X)LXo75 zgO|akfRB{p9Da8+EVVb28iJ4Q`VfA+G86rg{F9}Aso0FHzQBt{iKLmvE@sY2Wj|)VX2;fRvo1Oq*LOVn_uoFqkeF`1 z<;TgA%$}_3;z3=0^YPHsry`8Zt5$(SVC9PASxOiVQMg-H&gP$p!e`MiEOUDoX z+(6H(P})IEGBpHI8CwTVkwm6B#K&C1e3M?k_PR|rrXe3tf(eQ#F|6c(DUMQyzK)-R z!fb#5;US0;DzhPEnjfA<`96!mv5NFPlN436r=MuH#P~8X6Jv<%)fLp}Y5mN? zU~tAH0=f0`LDC8U;9Ck|i#PcZZvsva1X@rPg2nEl60%W%n>AegEJXl*KYBk)xXJ3Nc|J(!Nra$Ks{vgZ;R544)CDtfY5w0_k4+je}6q*4b1f z3X<5sms4{l4Iib`>dFWYY?O9EDK<#&KeHq#p0fCRY667fa-DzMus1bMff%EV(Z;66 z7M}qI=11)ZG{UQ&uwoc@ixPH2|m!Uh3WK&yDIg+lw*7D;74I#n4Bx76Ev0IOj6<*FxCnZEugB^^e?#e}V z)wV72%M%$j?Pz7yhIWXz?bCnZ0QL}T=W4e;NitsBU8u0%6>yviA_BhYi{{s)`= zN#gvLjY?mW!AtN-DfDPkDuqx}lhNXlL0hA=oRKJdCjban6zS@OMcZAoH^%_+yp}rJ z!U~rsy8^i+aTFGs8wgTyG($V$6IiZmW;m9|3hRm!BAp!^Y|(aj)(DIzYC!lFWzbHh zj#ds>j3W@2x*qa6+Cb6y*EpYm5DW+rh6~{6FBlAuLlO@W3xq>) zN&a`dSRfx1CWL1g9Td=37M3_W13)@If8yvp9PwynDrs+Fi^kyuA#r`Eh5v!q5jQq* zJ%6~VfTPwBC>L!jGaT0@gsbm}e)xXD>!%MC5WyJ*|Md5N!(W>qN2dWfC=l|4>XU;2 z5Bu(DXCB?mkc1q1)%Py_#dCtBCGlWQQ9#I{_eetjV=>%Z^Q#!_KNbVys7QQ4{8e21 zh@L;y#5wmb<&Vrezl3-;_GgD9z(B|kvK9dWLhvf#O^H+dhdU#1J^0;aKnPqv{$O$u zf7`f1c3?s`xI#x z0in1HB$M4pNLmQ#P!~2C*^$i~GtI6Y$ zz=Xz(U}JNKoA8^*2+B=Qp8N-}M_l^<2<(5c4*vjq+yr(7>1V)iNJV_nu`=R^Rm-#f z5$Mrj_P-4Wz^~x|<`;s(Awq%>sDRMVaq&0V;V8k)qd#^_g>ZA_f9n&+sm}1(_WR)#kdl=desw%NC33hrN@JXHi_+l?{bSD@dbIPTac48|YdseNg>|sSU~R2T zfVW`$!u$|kpd}XT;3NtH+5Pp1ALD4j4FIV+V$7UPaYsFlzU5$M4m3fT+TdFGQ3Ec- zIIP|ZV=se07{eta3I#)9U?B(?EDRPA6w%`b{F=F49MR?gFc2yN0RQy?3JD70LP>Mr zUo!lBjsF1cf67GQ_}TjJGGPJSLimSF7`NX2R!#^XM*J=lz*+Zq8E&!vO$G)F;pUdV zmjlE8Y!?O={G(kk6#NHf7#KGT{#Ku`uplmi`Fk58VEnrMn+yW~Lk|&{5N^f$t(+h( zRQX*dEbxaOFz`Rv3O9Cte^*EZ{D({!{AYg%34s5=0)q(S9P#h?gkd6o=q4lp|D&7; zT=s!GZqi00}nc159@*R#AAs5knj`7 zM`3Lo(8@S3;)oF9KS{U*NE`u#!=NApv45}%(KF)h9zf~u_>^2-al~&>QrrE}AYJ|$ zzH?YtJAyqB`eR6>gEP@#AQYSQ%Q=eH3 zk=or^`p^Le7xympH)Hc$6&Q2ICO@XaX5_CvKA{JmUvhn;}S3p;@j^x?V!U78iS07!n#!zFaJ_2c_^` z=H{YdSfcm8Nf5b7Z{#*TJb$nuvKG?KGAW=xg>d5R?Fbp4sa?;nuq(H;*i|s!QGd?i zxqWecM|R^;Ez-F#>J8ORX&?K5muqhmS5diEPiZ28b~bi%0!HpN8$RUU>OhKToy#knGV=TSft=eu|IYM_^E)f)o><(-sFqL-l$+Y$RqN+FeFXXYO`0mu%Y8?EQOhr{dXL^$W zQ*FBxLz}?#01_&fSFBqen9*$7(IY$O?=MJM-+WT)&5e92P1*^kDCx30rlo;a1R1-| z{E#!{wLl7%BQA^eUg`-<5%gbdk}n^MA@&^*mF7DamQV=#L`zMTZrv|pqTFqp$`rwa ze8Ozq>DVr$mu_4h2xOzGKyyCIusZmJEJOBGIuF;g8GjxsHUobP?F^fPPfic%Mdfeu zn`cpRtstII{3kjj@n*F{DPA*{nhC~G<3gkUnZ+}*tdv5|M*s~2eJAH{ z+xcx4&bc&DW0g=^m-Sp-0j>q%DGaoaj$SAe^z*i^ZApOK&p9VF{##@W&`s+ zUUwBD9S!47qmTG&(m1=5*@r!E*WtE zX#RK&WChDB=`zfG)ON5Z2vqy=!0H)s$_}c2bK}CbR|xZ4YzOLd&j=!UWBOJ?hEfyU zadUI7UwajC4Oh1;Mz>d|y3AJkLxTLBfaOa<*})j2(-6A@vj@z?Esg|)&)oKmQ2iL@ zi>}CEx}B^jBinXHT#Tj$dZw^6LdLA=c&#F3=WvWO`o*kpW*`Uei>zCzYyew4A7r4s ziN?9;$#7Fb-$R5ezLN48oRvz}wIFEt(p|dr4II=OAz?kUsj>QjU2Nh=cL}Uk(evA@ zd%Ui84!jSdPv9NOd(|3sl9^7-N6}`7hbA8K5urE?oGo+Vm{bAS8Qi`|?sBb+YRe3L zz$doxljc|QQ7sz4r_()l?G?2LYvvPU9CD^pN|o3SC%v`*#-ots7diGQ@Vut1r9ACy zql&l!YlhO><-{w~U+Z5~3gz6iKf@T$KeTR8keu0(k?g7YAY1Pny}%M+mh3)-Kr_p% zThrYbU*k;fWG$P?CcvyU^QoS+a~h>*Gp@9|RJv`t${oDavZmXdulpzzSH^Fw$QP-_ zH^%=2*u&4uY?;aDgyA>kFVE=Arw$|^W4FlHGaHwf2)M{&Ab_C?CIWsD;2x@!S{n_~ zYYr=WFkKgYPr9ewS=Tmjo`Rg$Y~plF{<*|!fwi@p%u$TO}42k`Ey9(C(Q6#C#l23ZJ-WFWZ?TV|$|#T8B3GoksmA$LOD;X=HcwFflR2h&4ZkLKwx zU@9fr1|?pdI6{`2Vid$Jam;c1e(9w19k;lp0!eC~$$=POOFoO<%VC6j0VW1vr+r%9 z51MMQOt)`aUM(Z{*>y!g?T>zxHymgd%2+rkF5qH4{rsuE0)M?fg>^)mfEA`QnM^`oSx}6_Nd2G!khM2pWBYG8vtp?L--Ub zXYbHKSw+)hb%!s_+>DVrR*Ge`2Xn5$(!*ES!OY+cG3Mx`_B8w9hZOxOlBp3P{XNAp z$AB&I8ieS_dvks{U|qoxA>qioC}yZ*lbbcW8jH~kPwfs&?Des|bYKx7Hgrub#IPs5 zFOosF)Z?xK7u<%z`yAC)o6mchJkGvGPKL2fx3L(#I_su4;qd2Id?VP*Xoo7Rq-sJi zSKaMZrf*>%r+(D7-Wd>FAz&(Nv=y9rPcaM+ziM99eOFo^D(4KQUF*ym6{~b}3Yc#7 zCiwM&a?ijWPj0y;bTD7X+D4yEF(^}>_PaajSL&f^QO}UXJE%44Uu-!OQ{7tssYf=; zW9{BYTp}oaVV!MV-#eZQ&Zyrm^*nRLUunz^g{_OO8eu_+1C595IlB)@rnTo+s8ePL z!gf3vZhyrEhuNOgRtwQea5R)ScsC-5saO27`p7xS$X;|tsCP}LcsZ@uxws9E=7?-j z2@{Vy&j!siad-#jfaFDgpFT?+m&l>b*SF1QmIaNxGyOMG$~13f#bShYxl4s<7Z187 z*wUSH^pT)_6esqu=I{%SFAU5OdMvy~t25zuuSGIT8=~a8SH+EU%@9w+O#&jO?N=Ul>}KDc#h) zGmlyJ;3tdV(x5w=@Avhcxx}SR>PA>!O>54rgQMz)f*@sXcaI;J-yD3(MxCijsd=u3 zwg{plkhKY&a*FLb*pR!U)bwb|qEs-6a&~=vX=`<2@Wt)f$7^4<6J)M5NRV@XToAdY z5C`w({HA(aL;pY)_tCeM&9QRgEEkRNEUxdlo^D7Tk$uuq#ocaYIg4CUSffq0FIP%( zDd9YKwmand;Hgi-wN-aI?%bzI@-3{b%3)Z!qWdZ@;Hh(R)v>q>idSpaw@Rcgxb6%D zFDlUVjjA8;u|(o?E(>sO3$#zzQa0KmvmHkO;wTBnh|lNVf}<+K3f=2=Hs&T)XIo1e zMqRSKN?vyfMRfM(T2tpVvkgzbda^;atr}8f+a6fGxD{Qif`ETBy=PGmny%Bk^jZF; za|3tmjPe_5ny;lXiQW~(uM^#-7||)J%b#y6Uf9~&8k9V=<~VTab@y{;k8IXA3Bjn$ zD{AJru4!?8jJ;Dsu_p~PLQEieD3Ir>oJ+R-esAHWkVhIiyGytsTN@R>A zh72}xa8+{kaQMsci;KfZ-1_hI6ABcUgh7DdA7m5`g-a7D=)X|WKEuoA=lfH4Q#b4F zg2`>GDJX8xBh=fZZUn3Ypz06>hz6yY03X)IOLdA5h&<%Y-rLra0ZnYNa}a-HErr!D z5Xc=ANXmUvI(+`+YOJ%PVAx=s_^jS6zxC<%AfrPMssrymS$QT@=?@xm-F{dKjy*d$k5n)kOCa#moLmZnoBcPVu>0@WhuG&wot2p1;KwS{;^o-8T4X9}-$ z7mT$zcSdw;rP5|fD?zR;mbIY&_SaNy%g%Kk%cb+!L`5dUtq*Mc!$;*5i{g&0;!Hn> zHnqbZ=a=6fzj|Cm0qs2GQBr(jB|Ms}Ek44+U}w{51^I%bjq%RH`OSjoZN3*@6hy3* zDOyxYtQ?{cwg)E{Pkqa;^u$(5nfc*rn|7XQz&u#b2B0vM0J?>j!YL!STEc3t=#qPQ z>f2aZsb6&4IpLFJp84(2j?6B=akbyTK!53m%1^owlg;xtx?Z^(>GDlke+Ndow>O7s^M***(ioB{BN zqP8zAd_p!{Mco#Oh8=&lp(Ij@@@3aRj4cHy3thoH3Rat9s*l)lJk0QBc)fq>Q?ZiC z(yq*vfGF_7*IM%a?VvZdOcpL^nWc?aWn9?xl~C_qZflyeQBaFH+dJax(SCRFVo4IJ z#@8Sgua`fI2Af)b8zIB$a-b@!Z)tuhGYktC6rfh9OE99Bcg>1vJ%{8E{I(6d**@B$ zuOb^O34wG=*r4alYf7k`I+O4pIAWE!2??8=y~xcLG;&L;o8!X+M{tj=>5CNoi9)Y) zn%FV)hJR<-dqbIUNy&#XuM#zv>GE|;L^3dim|VB8L_@kq6~>CW;6B-9?PaZ`;{MO6 zK4F&NR||FKAjT#5VVt{GXSezc6R)0py}x#Bl+g;;s1k41VV7lQGbr3M!SoZ8i_Hb| ztYDs3l8%~*OI2TT4eH?gX)RIj|OA9FO$fKB$Yxhh5z0MZt=9yT&>ooOc zcet?NX8+erpVY1_TH(7WE1t_;Rfd6WsyWY>GIyxtTN3C##oTS4D90)$mi$AX^y^z{{XHA7 z$QH?H2TkcLyia_(CtCof*2K9D^Ce$8Sv~bl(1wj=7e^tAOG5V$%wABRb6U+OOpiH- z?ah%J{V)s55AmDJbX*?c1H~4(TJO6NC;JsYn%@k^nPeR{4DZc6nDhxcB=Ob%^yN3H zL20~41@pAF0L$!#+OkuX!~K_KsHqnLE0iX^pwZd+;L6Wqx9E0XzYppStMLv>TUG4p zIQB~Bp+JcDx1e)Lp@T2elMg4sBdavQyKJ`}T-FekAC7Q2QBidaTcOucQLwO`xA2Wx z-;4${BUUHNEFPg(Zhfk#r`?yfEFQ*P&W# zYO;r1BBE2M??%AR%r0EnTwB8J?i4iT7Ms`KFQ!d?sh>K-eN{$HW-Xt;-k`5Q%(3A9 z(cxB~G9_oJw>flMfYH{6CI~FH)i&Fp-*oD@p<`uGCr9*)ZD_#Dq$tZo#6&D45J(Rs&ZobnO5RB>XJ~qkZ76CEE`slnQoJ@a(ZP+_QP5# z4ntLUVM94;07X;Y))KAW==M;5=KU?bF3HDJzC&X(L-|XWHIdaqO{2~9#w?LLBdY`c zBdgW^k35Dgs4i6qvwK}Z_DmP2^WtTPTf(Yrbd0X!LVtEQ* z;~DT+Nm9r;^5LQxcS-cSSx+gQZ0v04Mj-W?&=5<5LrZQTYVJ5e;EBn(R!atc3dC0Y`F!t3a>guUJTU6G-oq4gUSTi|jQQ4~DFev;{ zUxg?(Zz^mcU~*yvN@-Mg`9Zr|v&1XgV|GG(#qUhFs&uweu8r|T#lfwX32PVE*m?b2 z17++4Q8t4I&hErs)drg6S;q=kTlg&A>%qX{5HSv1eU!0Kb>9T)v>)%GwRM8gKYh;c;$npLQC*c^_@m0+m@(x^!J})zwK6^x=VpeYtdIjyKW&b`Ur^X4xoh_(@>$MRT|gNIP=Ff(4Ip37|Jx!mZaN7CldX#C*hq_Hw*LHc-yJjQi;ot8s;DL-^B+w(zWp}X~gNVdZe)G0Pi z{@Vk$!|`Q?&W*O{k3|o{Y;t5@WAsx_biSuIz9n=%SjKPXW%}3nv7PWwU$hmoOx2#{ zXFktjot+yyHn;9`{sXUrjq$yAb(E{@C}$@3jBW{`==uzAvK?u+kNGf+98pl6q<(yrLd>DsSWeZfS|C$P#jwxbFKrX4A4hT;*G6oeS38{e=-Pdgt1S8+ z_7ayE#p;U-6at^GH$?P{FS1)bo8JxSbLcN(E4_=X!Wu?7CP;42FD31!w{qngF4j(M zMZQC8#-B?bdaf+Gl^MF8oZ`*1>MS;F*>Ufd?zLINvOwuI1Nm=!Vk=*C53L!zlqh;r z;fzwh8SRp%-*(&3!Yum`kNn@n*wcL7g{VmNx(9wor$um1z<4ZsVx~x3LhS}x@QC}Il+vN*kP3;Q4 zy{TYDKvpuECPh&K^+M;Mz_+NTL4mE75I8__=*uld{A3X# z#Sn3KKDUVzP$If@v&jjdc;3rkJf}%itFEq9^n&3hguC8FkragGDeaV&u#lBW#rfxx zttJ$Rw7a{F;TXVM#tFe7zw`D+>uF8lpk6=)QEVQcA`jY*9e5~ZIY(#pl}BYRvYm(G zQS(AdQ-#taUqe3oc6i;VL}1$3RE&0XD~Kj-rn!?_cuFgXTdWn|e)fx(G0yvysM(F4 zxVwtetrvrYdC~>ab-a98s@(4ke|T4hQ+?WQzK*1bKWDW9{kNO@o3Jde<_G8J#wC z3Usn{ib`dU6&x{?shE21JCdg}7zm)A0$>5;L3%-~fE^Q&>E`-a5yNV;aZpfJlbcCz zNRykd7|8N!N5~Z5#lT{@^N|+*3+ymIL_)3G$0l~~JY`GD1d&sZn`6RR=OCr(e7EiJ ztZX32`zH2N>JMH}QGXbQYLBl1KTyYJyCo-_#C=v-J^S*RT0&D1paK_`P+?Im2-g^6 ziF}zn3xhiW0aC+IO>}Nk#571coAGttF?=oEYZ(7~af)Nicaj1LvcCHKIofCq%2z^X zo{Gx~ow3rpkJ5t0I5w;D3Pr3vKS&y; z*;#{ZqTtdTX=KP%zAzPa0I-Ka%C5U8raOdrFw~Bz1R{40osy3RxYvn*c*+2vAod`8 zwopSid|{_EJ1P{=m}wOqar0u3dO}o$N}zHzd9pHlc+d%Bi&DyrrJPP-Alu8J2{2m4 zF`tQAU5OCd_+i$%>8(n3LnXzoljasU!%5%&&ngKhgUs4XcZAz;ciyS z*N`_m>z~bo&QMymY#Qd(N4`*aw!{8W5ZFs)R3JDdp`~dwQ4 ze4mP*=)|0Q+;m_0@mfMt1S*l z(vI}7b`Hck*&8ULM3jlJCxBpWybTslDquy<+7P7_2ZA@zsPF0K=8SbADKij~8UiMb zsEYN#;2qouI6RP8x{?GIun`cpClnEtn6s+qac9n|qR?)@y`g(719lE4w=q4PKcSBE`C2lidS+Eqd_A)&y%x!XUP`wugepnF;MeM*06iC`5a5?Blx2;IvbCD?y#MqF!tHG}`hW)Py@ zM`}p=R8ZLG=TA3@$^Fauee2FIBT4c6IpHV>5c)$9ML~g3l1rpe5*`1M&M4vxeoq-N z@c|o;n=5uv5UIa{RfT$gJP8(YK5+salFGN`AX=eTZ6o_7g|g=#>>`TrM<>{DO_B>E*7%GMzQ% z9gc|Zb?s|w*X;GPm;A4r&_DElvN4}I2`xQbL?F-J&@}sV_1cT%|1=nI;=KRcW(3!H zIswy}pLiwl8g4*#xW?Sgmf_Ap^fdpSW9H^s=49|_K=40c-IqE)H1+?_iTiKP@P1*{ z=_bK_I&~lxn9_VV+{)I?UD}Nj{{VZy8ZNINWDc@mq7uSa z$NY$DRo*`W-T#>V-yR3Rug3ubl7vY^B_*IRamk<0#ouguPYH1y{c&0ciejuV{dm&Q%q+kf*&i|VYPGT&-*~BG@>%;Fh#2;fwNkE7} z`+GYGnQoq?G;o^U^ zBZg{UtO$5Cku2f&UYpW)@WB#uh{%C)I8xg0ZTWk|crWeuD2@jKjVJ7-8$wzN4iFSn I(?$aR4^Mc^P5=M^ literal 0 HcmV?d00001 diff --git a/figures/aColCPP/aColsketch_cpp_elapsedTime.pdf b/figures/aColCPP/aColsketch_cpp_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..07d2d8d734b55064425130d1121a2636ecade217 GIT binary patch literal 10020 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 RNH-~{BpATUtE#OA_#b4}etrM| literal 0 HcmV?d00001 diff --git a/figures/aColCPP/aColsketch_cpp_froError.pdf b/figures/aColCPP/aColsketch_cpp_froError.pdf new file mode 100644 index 0000000000000000000000000000000000000000..33380a8b30092ec10a3ab5446ae96f0ae6e825a3 GIT binary patch literal 9658 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 literal 0 HcmV?d00001 diff --git a/figures/aRow/aRowsketch_cacheMiss.pdf b/figures/aRow/aRowsketch_cacheMiss.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3d5449de711f04c4b5cac0979777c848e39058dc GIT binary patch literal 9368 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 Lh@W3gPaX6>Y^z%m literal 0 HcmV?d00001 diff --git a/figures/aRow/aRowsketch_elapsedTime.pdf b/figures/aRow/aRowsketch_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3e5a2c4b489f771f1c8a8a01cc44b8b3ec7a0dec GIT binary patch literal 9558 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 literal 0 HcmV?d00001 diff --git a/figures/aRowCPP/aRowsampling_cpp_ebRatio.pdf b/figures/aRowCPP/aRowsampling_cpp_ebRatio.pdf new file mode 100644 index 0000000000000000000000000000000000000000..912858f3eae619a941d7f1721dffa1520b943878 GIT binary patch literal 10151 zcmch72|U!_*MC&hR3b}~G$kR+tj3Uii?R>dm%$8UU&g+a7!)E~k}Z>cU$V< zElqda5HlFB_IBp>aTC;szy10yxygLXn?c>HWnA!46VH}6>xGPw`qP51g2K`lh&`4e zz}c;ZGW5E0x!di)r&5apv@;pRMO%$H_?zL@J{e1*oR#Fs$p<-=_?}g|n7T{Vv!`(v zJHtocqFnUG#(eQ#!d zpX*ZB99G{gesg`BKLsf4G3_3FVRp+8(dzX*A^xet^J}vriG=N~?^)6>Q>4w?lJWus zrCm(B$L`i^o4>XeH@6YqN1vt2OQ#j7s2Heb6|HFL7}9(| z$^W%(+#J9hB6<3XsdP~XW2ecj&M@wS^l|#raERZQT&QB9dxMT*cS`srjAn6oacuIl z6S2mco-mS@Aco%SSxl^?M-E%1;!A8ak=ciJZ_B`iU(OvRwMdW^fK={$`*7tHk)}hA zRB@k9w-~gd1!toCvPU8GBK(B|6TQs1)DWc7`6#JaIZXX!Q`||?!(KKV_M?M@;#goZ zUAT9yI+TV!SX(23Qkt7oSR%|Aai?9X#pI1Np}hLUN%42OgqvwSfGxjeiPU)&(D!A{ z(Q$8L(RtPDPY;bfNeGs5zxAZNmhMyYC#hhgG_erc>={guL>o`far&y<8*YNtbVhgL z2xeeY<6AZR<5;_KM;quSoLwaDIu<2FZJ*86I&rN(2Q-tl8fjMO!!%kX)(m;hSvH2v zez-v}EV~hrOVggB$Hs*hVTgHq%j42X6BeR5KZD0>fQ}GT?CwOjka>YSdrF3-T;=QH;o5Z&Z6%RKzt2~$Tt8RSX zmK^>5IZVZMsw?aWq0LvGnN~gOB90b&5lozs^X;jlT5>tXjwqzJ=zfMd`mOcRg)tlb zf~YVXpy~;M&SC!|w<#yslC&xfao~2D7{>>$+$T`qt~8AZSICC^a&Ap{xf*jH*LKbq z`m=+~SG*A1C(cH?;u(#h^R05KGAE-vUybw|9P>08_Ds2(Qc~)4V3W%uKb(1}Y-;KW zgZNm-6wRlbpcZ%bGbc==6iyZC1v28opr_H2L2}g+v=`Jxfr;CyFf2+MkzqX8u6pV2 z&5Y)(4c^@Sl?AJVxep4#x_7lLbx%KdzyIiAVdVYCPH$VKqkMz5Z)2^d_A^K`74x^a zUEG{g%aD9~U;(_Y4bc8(&1$0@uT)XmCoxlB{;P*vc@P4c;Q9)YAa*TW3C6nJA5AKc5oZ>Miux zq5!9I%u~gt5es0)xOQkgsaaWs#TKoo=gO}YJOT%%Y-+=px=r83Mi`>1Z-)B89R&_V zB}xxaWpIO4msFXJhw9yOIc~a4oWp*Q--xhUdBi9$feSym7%{RXKkARWcX<2>|JAVO zvWinYei~!VN_B&V=UTD8rw@8lWacrwZc$si*?4V2=J{!jk%RUjR9lX?H#doymlxRJ zRF~zGju;(hvF2a39Bgt1@AY(CCOv>bqkUcT*VQMJsL6v#rl9T%$lWO)Dz&lr_dm@tz7{ zZ(sR#6u!M_Gm=96?iumf{YR8HQ=`8K&j^{mc{+S{fKojiu=etC+LN`mcqL1O+LGQ; zOKYHKoTSYhh)MvSH$xxT6htBY><+GT?F7qloqfYaOwr6TRraQv?uEe)cN19iwGZ-|Se}~X{ ze;gCl0Pp1AmxAU!^C^H02tVg9yUPdsJo~Q2VZWlSRA4qV zCJ7sEs%+FrwtZHnLxyR65eDn)NR!RP8A{R6j`}`_s&~Z?I*!+!s;bSheDBiKUcR+{ zzi_iEqu_OYZFh~&2JcfBm&Bx{oTR!qIoW614sL^^!s2J?e> zkW~tmFu2vU$Yqlc{eeF>(E*fSqdYIznEu%_p>N~EyM^}+GkBj!2jSY~(KtV>pzQqI zHfza7w@WFOeYs)1G4(Tb@OSxR?{vP(bEx1f+IqdFM80pMKc!%n*a5uOuB$~JN4@cy zPF~^OOTAG^xGgDhX6{T1)Qhew;S(|zk#e#_8WygdS|<)$dXK@A^O>0D%CK!3OB_et9;1Hr^|_S3mM7p~fx=@6cQrI_;qy@O)7$4>^gX!L z5|6b+#ANbp+keVm(Biw_m#>Sb8JhpLA76OmX5PZ0tg-1G-%CdRn{tWE&VuYollmT| z`{+@SLpAb!N@^IKBJonPJcoS&q#w^39@%EB-M~xbtZ^o#y&mDQ0BqzIu z!T1T0xLewb7nddL{j%Z$?hCGguA`RDnTwhCz$ECi%UZMzjUlo*gCpr8hL>Z20p9j1o5oTA1pjIw|5?&4s;VbCSnb zFhqEqb2#1j+o1UNGLw+NZ#A9OmenjM2-`biG^u1=IY)&e;K-j@{7xcE7U}^Fe#)TaenrF)f-@T#TfIkwd@#+qrNpmzS&-O{Aj zFTYudeP&H`x-mY!kud&Fs7ojum?HlX@2J!j>mn$tcIX~+=VR_&2&7* zDocMwV(UOlp!?lRyhesamhEwjG7*q7dLOfSIe7$&%%C)ShShnC9^HwXr^cVrV3`=# zw!wYEW6_(1Pi`$?TK3<$n#EQUMwdiKpn@oK@$1d?+3cIH$BJ+~rGByc zBt|o&1}l>KG~$+|(dZJ(wAYvPC)GJcS(~CB0j-FZej`IQRk60O0+FRAUkZcT^$BWS zLo|xP^CJd;TRvT+*|Zj@jr__99;@i;=7X_W*D1qNs$x z3$N7Z(UXiC_O*E_v6e9>qaZcaDaITF3>#N<(lU&>ovweq>aBr#&*SvKo6(AENt01c zY2j)ls&rIKN`Nu@nodzx0bXcLHf{TpJ3iZ}HkBtzA+oXcs~WICDc-6x(E1%6bU`oa zv^K+P?~w(N*!lR?yp0!*CFNHJw`vr|Q>GEyQ+oEzNjMvko>k#A&hdERSmM!&Q;;=} z@?nJtQ^jb{Qx{jZri?OFgUyaTVgkw!!N1LgjBys*$0b$6@AUH0%+hY=a7?L--ToM6 zH^W$yAIW9x0A;7EtFCRIaez7KCZ8ZyR#oYF@~!0X%!e9xsG&OJ*?Th{bUJzZvEXWv z4H@AZ*|B}eHHr^$0#2PlpG~r38mie>7!8cu`0#9@*0xNk(ED$O)QL3rl%DB4J1|L0 zpTp#0p68=)lq~ozX@L)}oZqjv;#H&mcuJ^3o^8^Va%?I-o+x9Kz`V*-y-)#m58a}V7rFL4W`G@xgK*DOw^{(yr7Ew3TOZJvM zUOa0pY>g{L=CoNiw-3`f$d%~1p!OTod218KgE~Bld^D0IokdSchz%5e^qynA_DK6# z;X@n0Oar~_`Cz%P`dwxGnAdg>=n6ZgUs2x82sfN|&265Dy?DE0_<3R+ajD-VAvJ7f zBd1=sLybQATg} z^{|l7eF{M|Hn~&bBCx%UtA1MFAM^2=#~CfosIRI;g3o(t6^@~+&X=tnbCJ7Hck0a0 z&>PE77H5@OX79R8zvb#NDn5NLGf}?k(Xr+5*U2;6*nH8_?{yU0m+dDi4_zNOtj&AM zSPw-#$#C7Uq01a?3F@cP%(NU}(&TmtayF?MMt^)9Tuos5JjCl?J@y6 z0!WvIYP+^WJu*SXVHDS@djzVug*{zRieGAqAF{q&E8=`3CMvdOZMC`3_oel4%^3bb zbs@|0k?bugxX>}rq{HtY4i&2!T{x*T^zPkkTsdFi^|66M4{`qd;yZ)d*VnQ`vK?(x zUJWaKLp0ksvZWFozKA?`a-zkV;zkqB+qBosY%^KCN;p42ymFcM`jMsdnb16;_!f0?+t$M^qlezJuC4v)x2VAI;~r1WzvR%4GpG`uYR=XiWdCj`BcR4n=f&^Yc+4? z4K=F5^?>XZLO&JfU}XwRip{b5D!xvtp^q~LF&}yY1DcS;LwB|3CGJo9vqOfVO^Q;A zUqaXY_Afb63cnJ%+Ih3br()W%YH2}}y&K6x^cNgXnz*)7v85n9d;0+0hwjL)$62Fd z>U=|HGXidxuuYXNf-ytqRue0WWNXJRS((OicuBW;c0u$ z#Mc`=XJ3DW5k*&>1ytB{^b9M|b#>GHLz|%Qi?J0A8{5RQa{{UNLJ=O*gkuOw>ji&R zD?f%|X5NN%Ipf2@aL#-$R*XsmH=WLK%@d#nMdOxbqLp4YeG?R&&H50Kb)wBZE{5!84{Ig_Kc+xlDoa#A_+_HC%2hvE zoK$LNX{pmV-@T7{*DMyUie|CMY@f>Omdp!J5)Dh|7&EI$8ZfkKTC*w;W(mnfkEIM#|Y84~sq})SO znahh65R-cEdaThY!1WGAmZo>bjAGAJACHmOe8S0j@rQgPECcj(bZ_5&s=Yp5u0MYz zOt|pI_uCZv_ot`CR0%rt-iLh*i`_cLL3NPk#oAdwt=IJ0$nnZK|9Pq#t>8CZTGZQ2 z_cPp5>{mZfCwy*nvJ)TJxaVGFnx1Wxi#)OY??=2JN)$Xlk2G_OTazg&N z)U~%fb61+gK->8)dv+5)t{LhY2*@HGw@Q+n-)vJWUb3& znk-N*s~tXO{!#G~W`j;qDb>W5U)LU`h1tirXh+ed(^!+lA-#S4`m?c;xQ>{?0=~~H zJQ!Tx@v~hU-*wuJEf03-HLbCp)VpNzs{cA|?Bo%drtezduI9vC>_~G+3}m_Z^@$kp zv#0r-JjtmMqL-#iBP!AcuEy{ku~;tnpz-v^YvFe-thwgr@Zt>RPTOmo7Yg{{dDj`v zPWCV~rW+ZhU_a2=tvM5vski$=#oZTeMDqyKrwKHK@AlJSlk1giMioo5rJ2ju2-&Oa zDQq7S)}=Xp@)tK`^c9|&1Cl%z+h%z;6h!%pCuVu|zrL1t&!n$CeLEOXtGPbxcf)mp z=;4*I_)vaJPr%0;@I7mhBKU@CXzAcWQ7%hvpTne(k}ag~@-54yW!SOzViVXg_|$CVn0122^Cz zK+*<$>uP%b%}1oTE4-`8B+0ktoSW`srpH6CtB=M4INf_ASBHx)>wi2I@_N!Og}%xq zF`|mWWpK7FA-&);UCl>_vYZ#v30gNsL(c$4&YnJ3#v_8D96`3*pbA&7JaWw5FAivC z!dfp8V_=%^TCkTb8Q5N%-4DBDU1UmZUtc5eRCsHySY25YtlxnQfbbLO&WY_(D+9NZYN0B{{L)fI&@eC$=9F-VXX zCu9~+YR0D6&!4%stW5nemi64Hpr#oGgwV^8GrkH4MUB{Guur`7-A_&Bg#oPdb;Bj9 zLW2^zTrC%X15{maR2S5k&)iXCm!9Q1Ef-)SbG3jK4dh^M6lF&A^961|@bZsY-?oIy zA7z_~@k=)eKfV9;BS+%{qmP)A!*jaDDHT}F)i3D#TyQz>D=ojsK1Ri9-knK1blYbk z2t%9QJrpJupD6}_h;UzI>H*LYxCru0K^g^4IbZP113`=I`t?jq>^1<>*$b1ODuH%? zJwTF|>9MhM-Be(wpK$(73-HN1b}Iq>>cFGnw=9^pJ1#dB)Di->U(sykt8Cq%s2q(^ z-n(^!lDU(=@0Wm3*uU?OOpTKv#%N=Vv8l27gz?0IeH5^LTz_bu%+>5^Ug+Q3H&7L| zYXs81-e45GC@u5;@k4?JM{wX{%>-pl>Z5@KhW!n0i?yJ$xAj&pxCwu(se0Cf^0W=5 zkr=OGJVT}WN3U>INDhvQwDyP#6mk>8`0QmTJWS5BA z9^Th22`ISSUqffUVYx-8!J*rz$_@^iN5ZPLfbk4K%}ZDcPBi?M!^KJnzX$$WT zok*M;beAL}F>M-lnzpzdatyjl9sYJ)u$SBWhmAWnE2C{leBT~0JItH86N%H?b&b?6 z+s6k1lRU!*N5Fs(K_NJau7knIjGrVKA|5CNCB^?PUObQw3PX?yQG0m|&fJ3JX8=h1 z=T{ONN#aRyrjoYi))?bO=In3c2)8{|3L#XnyY`Ig)~1J`yAcAHdLH`i`jpopJu`RW`kyH)>n@zFG- zfIb&bLHv46Z|`Kbl9RVajI9K52m?~zCzy~OA~t-y>LGEl)k>Q z{ytb3Am9&Je~Y3Yw-x?BI}Y|AtaiV!s&i+aIJh6fswl0fM4r@ znQ4;Qe2U8dOJJvP}oUdb`t%ap|F#G XJK@oe_?-|Gf(t}U4unb~`uVON)x=Y{a`1K4xNfjJcb2oMZ( zHn#(aiUL8}UM@%=NCtsMI5=AaLFx!=Bnk+{7SIHWivy5OmbilOUtW-Rc0vPT#|1!o z*UasZ7HFW*w_7<+w1O5Ifkp!PzX{Y4Xf)Ez2`GTO1%R|{5SF%1)oGpn!%i z+!F8iDs&HOC>QfaLFj7<%|Y)TRZ*{oTQrRIyQ?1^Fe}rODdfCaN_D5qy|6i_Ud41D z);F-@apZ;a+4;J1<7gsuJ$rJ(f6d{D_GW?4+nT1S%*oH!Hg_suWtAWBD=*BwoA6yQ zVjiYg53e}PTlIgRpJXW}9iTHIaDA2~L)^XDL364r9@*-Pe9=5>3t8M^NsR6Lc?iIDrL! zY|U)}Td)<+JH~Z@T2(WQd7G=TQP?{moyqyIlOj82M_A`7zY+w0q)oq6M+RGt z;=%^Swd}Ba&*-A#BSwbbF{);Vg#qZ9*z+}d*_vz!_%k~O=&VyG?TZ_Gzgo2F|EM)I@;25AcPV*!xhbFld#wb`2JNGlkvv%9dB1n(!3G`(t; z!@jYlKAvs>p^+;>o_vVX<{Ws|P8Y`D+a;(&CZJSDO*6ZnQL`WI4b_xN=!H#+<;aSy*VpsLzx0m*F{wu`Lp5th16oH~E8QfIJL_aiSW4cxH_{>X zq?z6{V@f(s-aC0pDj*@n0$rA1Umx+}ta*d@r}|k@gYh6BFb5xUpw}=zYJEYB9uRExBMW)mlwb^oq6T z0FxARaY<=jV3n-brgUx^b5!I#0+H5i5yMk)nX>rC0_ys}!D1yIb34Mo)PN#trPgdw z{X6b$K|HS43BpgDf|@^xwr=(vca@)l&jo}n3e8wc zmgPAwu--baHIh}`6Os_RJ}!A@KJWy`hgW5W1h9JMo+M$T6j^`+IpwYi#8fZiQUcI6 zRcc2bQTt5T^a|*0v4UJIAU49)oR^G~$VQo0oee7*9V6nszg(B;U|5zSi3hU5<1RaK zA?{{|=#b0i$$_F+1MDrGy2i4uONe{nB}9Tj9pP}3w5(Ib|-7M%*M$Am4h+cA;BV2-a zV(If7N>bTE9Mu`r9eZp@@G8A)iRn%^(d^$|;X@&w_md>GQMAcw_m+ zC%1Y&4zK5FW2icSV`R712jlAU&!odjnTW(ZUAPt$xqHk~gC2byR-x}_8>tE^(h$g^ zs3Bq)%#s4mEEA`+1+=*^k-^ zQde0cDp2DpBiK|xq$j8~)enpiEKC~K)KxW;ewIv1IT`lmTq}{CFf2^`I$PRmMsRB6CbQ++@?A z)3voo3CSq3oO1h#5LyPd#-hR73H*#}I*T$a$2^o&bkZjXYSJ3+QML zBB&&$KH(4|R5liN=V6j`XFoyR3$9wWK)+Ltwngh;ezVq#$!*kd=5{rrBjNZxBZ~7$ zt?KvpHX0>WkQ9CtU*hOi@arzg;IS}-OPq#vGC$IKYu+x^amtFZFIpHVr^_q9$V9hp z*x{*C66fzVVKGhg!Q7{^j*AsC~0XzzW7HkJngt59n6Nb#@yW^|A?aScD;H6~ch!+xf zK3e)tn3*^qknLYgbvRec7)n$^*U7)hg{qGV<)WlwafS#HrQ+XBz{4XgIY(j@LCG>$ zb@WAXv4PrYOqIc=W3p$T4s@zq`F5c|M z^GGGeJoz6!7iAmaR0G^(ZP0*I&EAqC$5bJ0o z&W{ZjtS(Y-Px1!Z-KI3^Fxp$xeJxVXXPVfv-2JM>nRtKh6#-j;cnXI>VaJQDcOv%q zpDdkDneLLjwga|sy)|^xf3KOY#o z{DMl7fy@4&g|f1KE)QK+oU9`+;G;(EAh~?$+2+fFJbb-&?Fu~M0+_;K zLy}O12fzjR_Hc8jvJ%Y$JC#!=3{%3HoxA!&pJuc_I;o2Lk-Ntz2rS$f_2@QzFl3#X zd3dn-{3zjwZR)}DS5P4P5%&yt!t?Ivln19TXKM2VdR%p)zZ@v+c^a|#ZWl3n+gdIw zC+UFLarg86fF9#1`KiHJ>8#hrB&IXVFF7f;G)=6gG($W${Vy1;E3X}1y>Bw*=UMeQ z>k;F9v5kdcMRcP3+UScl-_hr9P2XwfXMxXgEwd%oTx1Y&bvm__gs#h-Iow+BT%9^B z^C9#Q|FkG)&FQmFt!|hzu1^wr1qW`FhnX;;&m43Tb$&E6kdKKJBSTjyx(294TD zTK0Cj*>H!hSoEWbC$^`SB0dd&k4Cw> zOx}v9ni$d#sAN^YHy3)>wY@g7C8xS$`p)#41THoC9#wx&QjSA#Tv!f;3qyWnF2}Ju zPG|@;{vm_n;`tx(`?vh(IH>_?-7rTVr$aa)1PGEwppf65C?Xx)k!V{B1OO!GgbnI( zSq$j9t&@}!%JyG^pZO9Lm+<`1@GV1t0Quoq#h~x`0t^a=W3z;R$QA~!`x!mdNjgeg z`jX(|Rk>kQmeNYdH@nSb$~Wud#ojSQO~_OT&NqpAAcQAyBa6SWm!Chpum353OP$^D zphkP?%M#m;;XI1b#Kh6&-gc{2yI2R>mBN~(I}xSH6C(%q;vX54P&cQh_7bO7g}a5L zfT@b>XgAgFICmjA4U%ZOuJO2)#~)un2RrmT;Q>YV-h=g@r0!-WAl9snZg%&tov+i< zw5RicycPu6Kg)zKTWbZEoM{e?eYo4srAAGTI5U@kw9hvBB>DAZ^Iflq%RHtgFYG#= z(8%70Fd44r@NjSoy|9FyF*K>l-|+59`f`4%<%|_A&F)tzFXur@OjYfiMQ9x2OVP_a zo5*H@d&=3&C6N@#6c{3i8YiFO;#Z(*T_5tcWW&MmSGcJ_wzOtXT)*3hJu^){+=cW#ghU$uPj8^IRb!h>boU8gTvJ26| zJ8~I^AH2{xrZwr@50qjWTK6@8g{lemU3VQ;DWEHc$qahb+kK~3K;jn@w)6MixRsPC z41TRvno6A$Je)OjX-c+r6z$y>$>5ku5Q$48Ek6(0@h%%yx^JQK(C7T6PhV$Ev(!T^ z$)3^z6^Hl_7Q-evid~*0SMlHL<2kcH{w0@vR#QA=J<@rern(@8)65mhN>N)?(=qP~ zb2UhzOslA@H1y&9l*_#oZq})x)s?{7m-V;{I(j7 zo)cSN#rlcH*sP5g%^dFFM4JwMv^=Dlb|zZ2MZe|b3^`RUt-E!;zmaK*&}#AuFTYwr zzu_m}YRzY}!sUw0GamSpvk3`lvUapATI|*Lx})z6eIgZ05SKqqzd}`NZuL%dpcgS( z`x-8LUM$zKhZel#I3oR}?BS+oD4dh8(4*jI;HIR$CihCGZo~v@}fdlRI0y;2`2)TMEx@b7<-qrf`)n zF?81=Fs}8}!%PKtdcW}3PL{eMc3x6^plIE1k@4zNy_TYQ$AIU?hB-^2^7}^JulSG? z&W|aII_F05BeJ4Q<~;J6rsFP!bPl&CJxSZ_H&0BDoZri>Gw9TydUzpR7yR|9`#N0$!n@p8(S3H&BK%Sf#_}9$D4LUpKOQKVM$nRoNb9x#h$a3e~i6;w0(RLuh*<#nwj~%a(98lL))s? zb^WpHSG}38b3E8re<9S~N3KMMsJ!@Uhs<4`t@b?A(9p8o2OAdE=7k9Nxp$nsro{}= z&yy4@pOS4wO{B~pS`~x+E|FS{AxJ`P{bc$>!)dNoH@WByPiV@+0!a@&U zr!OOX?lzW{nQ7H8{iv6KuWI1Tw@HlOFg&t+WV^2IqlvyxS=?`;u@MnBaHCA4AfZ<@ ztvD~5#-;j`K4VeL8E@jI&!IA=na1xdA8B3_N_zRBNC57>Qsvx6(kmNW9Eo?es#lyq1DxeCuO`vx|0J%-V%HT#rFpFba!&Xa@?F!M~77p1e+Y)nA6i-KZ~}bP~^52 zw&RHx9Xo304{7a36E6;=DO};vJ-wMZAD%Cq(5yWrCh@%bs6JrT5S35TQsQHwqhMh% zXHaBs-lhc`8qA#9UbpFfDD=VSwW!I#?X;=x?fm&=Vy$wIlX41}ej<*+id6bkN3yy~ z-Y%k{^?Bpi_q}(68sTXq5qe9Kk7fc{A;Zu{6={{v;ky9@n<#vdQDNn-TfP3}b8eNJ zD>|$_aPG7~q2c7|tDnlhDv2zFoTPZ)6SIGo@j-0u?XZQcppX*g+0qR#a_GW#QpJn; z_cS9lJYEOyuP5DHX^bI0E0(zJEw@lUeobz8&V?gsVy~BFVjY$ywtYk38neEkNjajn zc8+i83+QMguDpKlFpXtVAU!%<(0dL;CW!B_5~yw;Ks`*yQ@<;3cB-$TKK!h;5XQ}{ zRMHG#WtJDyUFx%DWej?y=CtF&bG!cCQd!wj$Ne*8=}-9s+*a@mu8y_Rvj+7_LP#x| zj36L~B*$n@>YOHT2UGbENrKl<1==J=oHY>_v+4Qo9 z=kt4{@}rW)A~V@1Evu6UOzazX>~Z>0E8J&byms--;#O9%*g(kaHc|+s)_bNRkH<c-}Gk0V)cLcke#b=uVXxEh$8b6x}=u!6P8ZOpUD+a_xHrTaS$U zO2$q^c;?Lx3!uh#ZfERl#bV$R(al!ya`$!OL)u4Ko~bU|?}-yXHlUm(2KJ)8uTHD5 z=S5Go#P#0o?hdVr-$CV_oxBvUwz_;RRWIQ!(N0qTh1Lv&cB3`i*?!dCU@+}v+@w#+ zLuYp1(>($Dp4!v?W_@?e>9%{mHc@-*^p#->rlhaF<6ivSM=Opvy}~E1)jskFV8Zrh z#G7UcO!O8iE@m`8GuFTpJoT&4x2xw|+x)GP}&-S>2Y&k|&+9gN3{wKXD^%-=1aZ-aFFoFta1 ze6(MeJZ|Q+Y~#^&aCcKup4C`WSS)0#c!Dw(-154BgF7YtzS!lt();BZ1In?yr){G6Is)A zaaKLw2&%Wm+|>3oo?)Rj(SoOMWHS}?S1fP?IytVjSz%&0w&vTk;CsRTvrA517rV#8 zsZ0)*oEWd~e(|o#-S7aY0wlCN+ak|3Y}P|w`PM~Rghy}1F@#6&a$PxitH!9a8&Xe! zSz>k7o9RK#Y()`wW9IZF==GjGWtPx|djeIMwc+GJ2i=YB2mYeP-BI0*=E=9KFL)Zv zJok?GRem}d#NpK!vprmV#c2I}*u;!yDpjR>()~(m_rZm>#LU8v6xHjluX5kWBwoKc z9?k?9V_~@Pid$3=e+=H?s8zJB@YF4bKmyQ2Yvr(+77No^ZMM2%N6kE8`6%+T!wZYF zdRD+$ZqG`V?EKiXT-w*??)p2lM#M6V>lGBL&D6Q%k~KUb&(+O(CyV5`EK-zBwE#c@ z(g96Mdd~~%llZP%&fsBE?Rc!!v(!_juj^$LYS#%->?P_^28m*PXlS|T7Xw?z)#d}I zi6KQ>#LPUJdabeNGFY$B>(@u=`xVvR-YZU>_r-LmcWA}=L|$0BJZ@nYQSZR~I1g-} zalu*+VO6Et#Sd->S^;X8W4f&*sG=R00`^akiTKc1RusgzR6AUvE<7k{z}d_O93bjmR$tMeW4fooDzm`J zARlBdt6a#40J76Hh|vl5^WNQqpcS7nzH5$BBxRnD4ahW)Vj!4!>SlIw{3%^ZRBn$1 zz7nIgCYzBzoBPGvGKw3llSCZWJoi&Ly_VM&&2@{QLan0y?`?qPK+XL zuy!FT_cNMqAb5k-sE(GF)e(T;VWJIC$B+}$0i<|npPAjLoxR%?AX0G427KE+xuVOq_?a$N=isOrZ&zFEu*gxk-7G^0BGlUt^ z%)-oi+HCsd2|U;d&c9TT5L@KkbsL5|bjRbQ&Q92@u$F3i`1f&pzmL+JP~6S3ON*X+v- z$=XOQy)7nj?1GT(l)xHNM_qR`*e-^Lk_IXnpgK%^)&MW47-nWN$ zG~*5Zi`{Uf)(^Y=HBpvPlEo#+xM$E`^JQsO4GmdcZds%qLidIi!U+WcVT)>cq0mT2 zB_}IqAdY&}L|WToQ+O{RrxccDL~;Q^*W4_TZn)f~utKdHE-ns8M;x&S z#&KyNoJLtB%EHao1?}txgyPshO>8<2gnlO$v8uG46_jLE5iY=E*ZP&b!}`@fGz!-m zY^MG*`~OR8{+0BDejw#l1cGp=u)7fmCo~Qt3d=J>zwv@ta#7n^$I14X4}^ZBOMlre z_><54w>BQPSqo#sV60_$`2}G>h>$QpmZ5~fa3rS` z4k8*T48{8YH@s*dFBB$-BY|BMk+#-0SUUqidOt3)3@nx#wzZIQvUWgXO$XA#_MtBB z0*4X1gMsb&M&47=^~vl#5ZEe7Vp zZr@-F;(o=&e`)J4J3l`S@T2`$um36hby89V10mnq1yY3oA-E>t%n1cTj;V9(CAJs8 zd$%gKFTZ&ZNL2s``N3@q0wLdM>z^8qtNeZZ{$T8X?sdsKyE$UL>W9-n_ymBw5Zw3A zFJr)uZ7T?j|DR_~$0*2|TR>8|out%ryWxa*`b^bCp^(kP97-A1c1_OrH$Pq9O9>IG zAV@tauEZ`}Q^v79tK|lP-Ql6vhILcA^^3yRbX&8*au3t$?4T2V+YZhdkPtjmOKt<7 z?%X2v9g0Kxu%6v(w{~vXXr+C;b6cPE)t$Qiji+;vLaID8UfTXu!#^jpW263$8Uywp z?BK!FTW6u_8?$`^Z(%wosLG98tj@%pLabbjJ8xv9W^@7;2?+WN)?d8n`w5Nz&yIur z2dmvrtm-{DxUCEL(ZGa;^iVS^7gu3dyc4AsBqVQALKgm3(ZFRR*BhTRsCItcYI$rXV0Rj+$lUBjrMOe)E+4 zXOy*nG5)VdbN*j#`j3bB|E8z>dT{3d94r*;(mev|tqXmGMUrsh`hH9ytgI}d?8NI8 z5`jN0`)BO)?Q9h2s;wn%Wj{WIr1|aG&<*T@dc3lHry`)g_KFPl=npPV;Z#MST^yXz z4z}h%cNm`#AA|>JgGRfcL_i?Ne?8)JcC+RJfYjZbEpJ$0PZIt5mW!no&>Uf5kJa+M z25fkAT)nNclPvDs6{oBS6byxd1tDOt5L6f}WWWXZxgL1BA*}#lAXFFt{?`X6C?Eh6 z09pb6CBv;VxDU|jhfG)ix4{1{6M_q1d-LC9!eFe`ewV?){Mgm(-(`Y-)CUK{|IiBt z|5*+U!v+ukRv!$83krVM0fvIHo$$L12Kx&>2>efc`~rW}2N(R)25=$aKXkx_1+ml2 z?|Ox?0oWfhn7|*lg2DLz&?_YHCq5x4E~@=qhY&yP550nLT%hoKIT$}bHro7MCWJNq zzsm%LaeUhE<%9*`zw{g04S@~*+>TEXYT0@tv3`Y(>7AW%L*Y1lIS%xXhr)6EjY1>b T(8n$)ECdq-u(QiulL!14z3()% literal 0 HcmV?d00001 diff --git a/figures/aRowCPP/aRowsampling_cpp_froError.pdf b/figures/aRowCPP/aRowsampling_cpp_froError.pdf new file mode 100644 index 0000000000000000000000000000000000000000..028a6803bb351222c1c6089298ffba21ee2528b2 GIT binary patch literal 10355 zcmch72Ut^0w=P9MBOpi-0U-zoNJ#-gLQ^_OZ_-PE0HK!%2#5*-N-t8BDoB$qMXFS3 z(xr&fi-;(_N;?VauYP*&cb?~-d&5Ka&f2qQy|ZS`%v$pfyPC8tFN9A3z@9e>%&h`I zfMB4bnGHZx6bRC~>4XA;q>vb-oud^Hq=vLYxdNfs0vbSZaRAD}0#^|J%L}rO4j3T+ zaRHF7s+kSS90L^k_EW|KBd3W$Vo*SVZvr(W27_{O01D!M0zjJ9NDH)s6%h9Qsf(kz zCJF;Iz^av&#X>=OV1OV6dn^RW?^mhsR|TNaFK{4#HUNhkhu#H+MfVLpNCV~Sc*DgU z+a4T#tbS#b1sW;o=z-M;#{R(sg!qIYP#`}P!UxAH07+q+hJD`^i1-Fj!ok52`wN0A z{Hr-|kAK)t3FTmgu?AwR!Ic5YqV2FP#$N5PW{^giJ6fP{z+EveD5O2WBe7Qheb{IP z<(Sni|2r}fU4DXW!NYPr#vweDc;zIk>t>>hWqrm?GeF|CO@zz?GxdDM_wA&__Aj0( zW>gKc*QSK z-MH)E(SI(s`=LrMxOq}^cb6-QnxyB zIf4;A^EE+eY!Fl>^sH{Tc5h1L;Kd=aI8+Kelq=mJLGR(SqY`5hwRKG-+^cDF{V1B$ zUhe!Q*F*0&wI83eB%Sh+9~W7)BxFOs!JC|QR4MwdptHsF zm0{L%^rr>b=a^egR0}lNayqcyG;r09fGIn1g(&S?F~2#%p}f+2`H6*@h88acHT_~J znOffUQsZFH9JYr0`v8_~wbwdPC(J|qTwA!Fh4^Zn554AhrY}dA-zefly2O@8R&J2* z#kUdbL+WW-yC)RD!bG+CX*NM@r)0x@s5PDsQY%D-a0>agoqG95W27yWYB$2HOgidB zx>P)`ULQBR0+{$-JxA_hH1_V&{^tnkK}3|+`FzQ|ywGx48EiS(*Bi8Fu!`B}$Vjwh zbV4K98swdU=}Otc*P=|7tnc&5Ht2B0bg?KB=#i#BQpLV82L$fiu$GT9-Eg}adPy^h zRlyem)Ia$s*BSfn{eJoGSMRuqWQy3ypOL32vFAWNNkwu6FBiD+Nt{ImF*)CQV{%}Y zDJ~t5nzB&F)O)ew!24*UFlBEq+@zvx!UErXU?={YIO()(yA=XwhZ8*|lEtQl! z#oDrXgB7rB(cD>OcH$H3#z`lw^i%Z3K5zy*#)y}V_alptGE;n(ot*}5*7q~u^pb6_ z0{QQ$C&mSY+#{0$xI-)~#|79fzSy_EzwYM)mbz5GH^oR}L&WGg_ReIp*PGt*ZS zp$V($7c#D#r|B)-qIAc2xhpxv_!$_<=QB79H4Pnps{C~OD}0@hl|6%ZU!j9Va8eZt zYfc>lypSUdQ)7|-ltSlW$YEuAP;7A(68d)6R7w}w!sh1}{fcq>(fbo*SEmTi?yI4R zNI$pBp4)%iuP9R^c-eEdH}Y;gzcphaZ=w*RZgebmQTCrZ=stCfk z5uV@@{(!_kz4Fr8{+sIXSvq~Z+){r+>(t5Jifo2F)tcf;Qi~C%c#4LS=Mo~P0QzbM zu==p4cPe60Qk)!x+I$>(FeeJiSb#!oSAgo*7LM(iOj+I}Pn{R;!zv4%VFK)Fo+A52 z)R|lvz1dv=cLRjm9j&-Kb?DHWES^^tbg#87RW#OcUJ!yyQBRsBkjtcxAfS}oO&`f0 zsjtWr$vjmEB%~_qatPyk!WK5z>(_FP_p*by@1AWi$3wVl^`m#`YxnEAqV=fOT; z4&uBUMdhTy9TLxlPp48m?$C3WpMcNSxO}Lts;zdrY_*l9j`|p%R3kZUN<=i$5##0v zvn4T7%DqP!V+N=J6|O}5xr{Hs;qnNy?>Gqd=WmtgzoZ4xAlS7+v%Q6ZBL6!M8fR% z-wqjcS}HUI&c~A_NzI!Xn8ExlL<8-TCE5@c{3ooZyIB~J8y`_bcbN<&VQm2YZH2ui zJ^aCms-%RitM6y!I&=Eh&~+fzf;*Mt{Q!4Oak@+GkVYA8=4&m&uVe^GAAP1@KW|MK zakcvs^uiYA!yxM?;KkQtM4ldGobr(`s<+ARooz^6=ga~{2A@gowON8O;DsNO5d*de-OM&pH&$6L@O` zd}VTUkL*evK5=N`=iD$5SGr!aW}nLuJ#&AK*2?&@Mu9}JW|tO_>V2$=Pn!9@k3N$y z&C;fk@28NL&MkUV0wP53-R;kHf0i)Ii<4S#+Y>6h5m6dx?eA3?CR?z!qWKltE;2eV zCCB9Vo#SUyyk+`nVf zUbz44bv&!uP4Cr=86#J5mJgb!E)FO15_pU)8+TAsRoj6X8zN4YSTv}b{hbLrvT|g? zZSJwhFz_|!us~`_F%L_u$KXiZe3;IQ65|;`9X3Za!e>;Tpd*3K@=457+4FBUvxgN7 zd!C&xPQRId#bNhL;^LZHSUaD0U0v(M^71MJmFzCplT%8qyS{k5Ne-vNi*ECkf~Ce0 zC}tw#1M0JrBc|F=@w>kM+?PxSM#{#eljU!En`NbVBMlja;X#rYVFflF zMV&(rKbEZ~t?AF{OpTYzS+w+Z+O$ZmGn>4;+-e$Vuz7HJ{UGsZUsf*qh*e_tHj8M# z><;4t)65Q@O2k=}7>Y4z&KJ~;p9lBPPGnm7S-!s1bND82XDcf7wf#g|WqB=%?c@Y) zBddMPbr}pA6wO_mlxA$Gck*1-S%NIK+LzV0pFhry`;1K5jZ)K5PPxSJu3U-Feq$kU zRDjz?$tY-3Lz57aK2zjve`+sTn#3S>Z?W3l@n~mwjG_W+XE#*WnLiR~<@cE-4)e-ZyRhAMJ>u~xRDsdQ7U8nwD=8B} z3x}sSS0WN{DaZF{`Frwl99rYTZ75t2@*^WTj>&OC1EA3l859?%|A@=K;LpS-_yqEyEb?iY=TPH@L||4T^0SrU?Vf?p=NmLNZ0Xz~FJU0tr&;iiR+{%q$yLwSNBh}1l|n0%wuBw+@|v}jdT>`g27TQ4+poK zG+2tVza)9RSr)4uQfn!i@iNL+!en%ne#Uz%tE?vP`LjJS&ww^q%Yccox|(?VSHb9V zv#sL$oreDEJ?RhvA`*`e43a9>CZ)&3I1+r}3HuoL?T)RGD-vF9lyoM`xhuRG^d>S2 zT!TFMD`Hm#Uwdc7jGm*>a;hsxi?@kA_YhKBlV-|3NWFVaFEiVe%k}!#YqzvCKXbc2 zx{rX2I@jm(mKkq5WEgiL@Em;k1F%s}!`oXy2xACdWjg zaC|yx<$1`qXT@8ED08J4uk)8S_NPs<)q*X^p3nm2hXoEkgp6~PI6Y3O5eVw%A)lkz z%VVF`5Pz@~?l?I`M2tgor-oOR}R)=xc~UR7Of;KjR<$2}iv+NG}9oygjs z{ixg3%a0yi2XD-d*v*Z9lUl2kfEIM^zQ1mk8{1gJxw&0Xp$+@pKwdDbF5n3yhYL(8nm zUK`XC88o~>DwZfNdzyZMs@%--ljvX{@?HH)xb%6kJo{c+@VxzqmXr}byPMab-=$6!!xDNOTz1zuEsl$5Q>*nc!K!{syRE2eolm5B0hLIp?SL;S zy`=wF?QTKD4!0tv-zHL6K%&V=Hu^*Ig5z3ukMjXkhzqr|o%*_{>M>_YdwKWZ=vdOD z^w###OAB_sBH0S=947lI#Gp*ll%z*9HeVg|WebPUyXQM!cOd(vJ1q}OL+azvr3zKM zj+Q>rwtA7a3B|lOr(x-)W@IQvXW7$S3$<*T2NtwoHb&K_D8ij^PL;~$DRO;(+} zK4Dx}@RFths#%upzH3jJGum>0fLJ@nW{_5!%kBORv)Z@FrKiC){idmaX9P^9N(WOt0aN? z4as$JNPG8I`2hCH-i0Y6-FZv2!_}1nZH^vIx@g~7KYK`P`!4C?V7i`G<$HCN`I>dt!u^y3%{+&VPWIW2h>PKFyx2p_;dwcz9{nDE3QVU_diG{bZQ#{MERrd#sSR z&}Jn`rLE8%Kf+a40^xUvYu$JHd@5&Ls#h1ZS$pB!>Gy=*rc5esRPHMX&pkLn`K34d z>lwy}vGsRD=CT7Glrl}1uYgg*ESt$y&u72TjMVYmJouuMe0!len&gaF(x#`(T;-^$ z%-b0!j^wf3KIX9{{&ca;8-l7#dIrXo$ol#jzTrL4(Mo(}an=NORi!LXx!J$9z$dQRF%kzbW_vy2NizW^eghR3Gn}1z-^3}tZRD*{Fe9FX zdbT5-W41uBrhbadYDwubYL`+;Im66>Pv1#X2Zcwo;)vg)*HoLrE_Hb3dh2-U8RnkdBfU;j8=@YA=55Av2A9p=4P2*)pE@nwe53>Jd6k@R`TkW%EM%=@ z>})K!^<^OkcWOqI*yWk>sLIU2Yq7kit=EdaXuZ5WCcN0fm~X{`xk6pxdbrKOR>UVz zaGjcYs*k!U%fuwj@(ZQo_6>g(lEXKlS8lG@ixv3KF!+=EA34p0PwiAOnN+UMmFKJ} z`sZ%$q%nO-+L7Y$DO}l=HdJV}0;G7Zw9oPEDv0rwOwREbejSs)nL|~_@E{mar@iym z@3#A7x~F&cN`m~pfuPSVz|pf6{NUSaq2)sh&-3Z?-#Aa{IIsCO7EZ6cZ1e&g<*ld! zcsD(^y?woPro0KpS0@u2L9q98phORDVk??%&YGN+fJU_cZ7mO@DQ0S8O?bx2vkQd- zRdd{cE)LapOaEw&wb^z}`0jn5>3N5n7kl1^QW+o2J22|(?0MGYt+)e}0ar9V+QZK^ ztu{hlcsGQbheoc&GlWL&aETneQDM~HdC*AdKhNr{JJsttwH86r<3FQ!gM{m9@5iwjkA2K%O zkw#VRmK;@0?KU*mo|ILzPFcI;{37qQRFcl^(a;Nk_sk3|FStcv1n=RU_L{|;a!*`x z39kTN(OTNArpNMYFSb~U*ibW#S;U23wtH@#-pC3#!|hSc{H!4M440P9OrVclTUac^ zsBU4A%2b0>9$C|4ioEODpQKS7mxYU;QOyBRfDFJZ1>KyY#$-Mniz$5nG#ef(wQRN2 zNgdtHBCQ4?%H1U0vjL+1UNp4avmfrYjjGJvn{}o-YcAC{_?1~X;`Bj)1!Q_Z6=GA4AQbjxmy6-6tDnrA2!z)gHkW` zYs?xY$zSo$DVfraPji~T5V@v8vJ}tAvV6aJRsn_>d4J)q0!&FOJ{9bfC>6HcTu~gr zIA8y^R1Gn7RiCqk4LC^L^HFUc)QG&^D+CIRRvK)EK5T9m?@Gz9u#OXRSoP*m z3_tK$xR0X9?HvvmPs|YqKt#DN(e?qz{W<;RY42+lx#n$Q=mzhvuo^bd(z4nEkUSS? z{nY#^2pa$rJhV?uZ`4l*cKZnz-mwOs3v%2D7|;NcM)+FO9(IW|7uER(9=;>rFI3&X zjbAkytMX^+2F39}zvoLpDF46bN9Lxf5L2Wn%GBJ{YSMJ_1Rg#=9_L@G$MH^oRFC-g z`i<1Y9Gid?W4km$m!zaWKTYu0Vh;{{s-2{wO+p&zPfgh9u~G+OeqgZ4<{`XPTix2H z>E#eges!Xj<^r+WJNfYFq}r<=oqGec1m$@fSzo`Pt7H`jszw3e<+6JH0#~n?IRkv| zcIB3eIh?}l6$16y^4EV@ABf3va9avveT?VTNGGpVJmz1`%}i-cyR3hHQJANia}PC2 z8>lv4b2;{23>?AN>&g#AZ$an;E)%m_&(?jF8qAIHk>5B8B7J%IRQqmK{ge7tg#(rR z6y^ShrBR!w&9=m=dc0njMjPgtPa{71ikET4Kf3X{mtomWMzb4933eva)8TSnO zYrZV0tgbG7om(1ZgS>u26Y1az0AY)2-gL#F>=hg=9f3GXQ3GX##-{K$ft(Up_7KGd z1gW}Mpj>ddHK&3FmS96;ZeoR+H=La8Q1&>&4vgc-Ksb%kC|7eAv=heB1qj8ld{|0N z2MGO67-CgvIm#(WD*8C^w2mL_GD-Q(WP+@l? zkPa9eMprC<2>r(QVM#+RM{Ni6G0zA6MuYycUGOJQ`Hwapw^;>gkL51^0CP+tTDfBB z$#15S{Kj1JLcmzd@Cv~Afe;~t0G4^==f{zk5;%w$AOec@|8ICPKwc<63`g!d$)nI# z)>u0OK)OF}vCJx#^F^CWI9S=Cu%-iPV*Btq?gobu%VT1D{&>Fw+Xc!<4;{1xmga-(jBxPHO;kpXrS1Zx!B)4%;2{oJGZwUcDA3cgXRAXx}*Uih75{dMk;fE;_)H(&ip zGlQfgaDdH`K*+HNNkISGV%Tk;pT+q9+hSlW6O1c}yNZkd($-&getsI@NBgl}|5Nzu zq@)Z6LcX;NqznNE5+KO!TII(hR$y41EDIyv=ibA?1;Jwj?HOJ7YM&E54{$D&smoN zQU1@@+n#}CV$vIIpkuc-?Hn^95AaPaxb?ky@`}~ADG%vGdUsUsY~QigOkelCt4I36 zx8du`lNm@6RXzqk{i~wEpOe|KQU6zs!T&$l!Q)qJn}({bO!o`E;n&8asx)-6B#%FZ zT(}s2-q29R5RX3`5bzhQzj)F2lNbM&9moGaSnYmdRqMsUZJQ&A1SU3R1e;nqIU}6$ z@yg9lp8N~gU%dN&39R71JK1-z1ZMnVn*N4-MifMsTq+{ITeUpvuRwntao?thzgrdX zb2xzcU{C}ECJ2EFzx`9HPke>}whUwX=~2V(xe zgN0&Ux>r!GZLXiF_$r*FalpTbzoH_s0`KL*Nx?rY`)BO)?aUKM5p986*^dtwX?!~l zbOXDf9#`mKx!_I7B|eXCxm`|%gMqLXofVm#cKIp12#N5t{&~^AdNdu#VIWe1w;A4FbEhd z1Vw=1`domY>w$+0$`SwuLJ&=U9`8E&1yeSi)>WC#H`c0&4HCIrVV zH~*BuuvYtB1_y(&tJyzgxPalGGVB2RhYSpc{ZS6gj}0FFQ4UL{U>DEd>jOi<*iQIe z#t;1qK8V1d_ylk(=kM>r1^=`GTuAT_9dHCLy!-uK1Oz*%{wd?f@m0T<s_z{2Tg$W7$A>$VSW24RA^$H2W{%8jbF7yXJgrLAL{ef{oVuL@IAQY#d1(cKopq#Dnitt}DDwTMycbpxfkk3bK*8?<4I~zea&ra>;eP@^2wS9;owE&4_{UW@v?T(C z1sdVHl~ce$L3v?;AY~^U1eqV7vOhkRfhNDef&6X&9ycDn8w!W+JA9B93WIicv&7kh z$B*k@4P|AAltFvpdIaPCgat(eL?BQg3yl4a>h!)MAZ7Nka|FY7EBp zRKA)VV!viS8xd)c@EMTw8#5lR{ZQNX?DN`wjr*r72mVfe`(zDe=Wo?+t1S$2UVr`~ zy^LsAV1BAw4}E`82eZrYdbM%4xO4C{Lk@PQC>4$gxH64cV}YGwKk}7YRc!VzyFh8x zobclP>NUGM6%%zD*|bax=?j^d?nH?ER584@jyiYoKz5UIQ!yvakUy2s9M zfqW21+1mO!hp{L_8feUwI*7X*u5&@=5n;!|oXk+8M$=6ZoyJ1_ zdpROrg&fV{JJ)!swPzia!yrrQAuXY=Y?Tt@jaMvQ&ACNmWuZ|a%Mo)$;b9h|RA2cX zglO%Ob%G;dm zG^fl2>5qM`ac6E4ZpaeOZmELP7=UukMAz2WJ z%h5*RZq<*Y;0~pq4Fq-x;3Vrbk2Se%0Yx!2d+@SaL1$o=O z-SO^E-TSGOW~*l1fKHffVq?5lG$eUcd#JzU2q+W1(&{o+uBpB|7VOZM7L^-@d%pl1C@=k#YP zV}*#>!#bL?p9@;LycJHHb3S$P@CXL9nC$wCxvWyXQiupFf6&?@Q3!#dS7s}mI)X1o zIj(=B?T-;KlqYElyLfgxx1+1BP)WhDRXV=KWY0M=s{8Z)o7J7Pi?HniCDfEw2sf~n zGLkm;opQXqTi@cM%s8{)7LATH?YE-sZ{VymWk+@Xn6C$)CQbI+a~h7;=S7&+nH?um<)edltf+Ou<$O)&IP|UFY(u|1H#Bq)=!FQ1A5ES;m-r@`+{dLoV(^XYP8{H z-p9FxyZF9@Zg@F@HOR-!KZ2F;?%9%fc9S)#HlqbchFlYdg|9Akn*9hpA)lhEewYy? zVy8dTe|-O(ayP@7i;XJq<`+?Xfef92qAzn5eYh6Rp46Q^)tnA3Tg#b$xRf$W1Kcness?$(2-vnXGEmML`h6K_Nke|uEmDHbpBDznv5WI>NoTGGBzf5IiR`Ag9T z1M)2=wx5pOqNV7Y?-P~{?BLzF$|hX~v&1-!Q*WwtlzR9fh9AB@TmRwTPR3 z7P*nK)~Z&72O3Fn6p42QuDLESP{MWZfGG)*TGgK3Iwaj_dC=O&a4VBN@5KjOdbW?j zq@@v22i}Ak1?&Rk{D#Dox|eL@bn{4c#B#Jwm-HcgZw+&uG<`s-!uh~`U1f(u4!B2Q z@PKQcrbLBO_%>@gk+G^>V8+)=2L3LD8G8nmmA0f;Dj9j!^i`XxzRvo5e!AW`=N9Ip z>1}SLc#06{WxwH3rO>pkC8NM-Bi3Bs7BkWor(riAGMC;B68|6_${I#|cTv_O@C;+M zQtCF5&}MF8|Gwh6G^we3eW0vh?Hv7z25QM0@1a3cQ9KBM#Z7yn$FXdK(WkOn=zMAH zy_GviRd&pc$!AYWJP&E0DeF(@Gl5veI&3tS+J=v1MoDnD-yL3i8N(?}Zz_U5g-*_+ zJ(EeE@Z?NF+RVdJ`z_s1Cu|?*uwS>l`!(aJzi8P`$Xqbbb&9M+oiHv!snhK_%sq`I z1y+mMFI8lV+EF%sf2+!}F#ZeVo^3Ey4Cl+41dPH3)i+dCB@YDTp7LoQthe3d>|2%N z;KLp$tnrapofx6dT(Nz3LOg1>EjUhhnOfp<4^LTR@H)$DjxO+zt?oUnJTx$kt%#LMm1A85nMVb}27SHCM zjv89XFI5nhwPNpvZ3QwcCT$E;*f&qj9Hk&K^h z{SavTN^Dj=(ZxswdqgwqsvE%SR8n}EBR14Ak$LS68>9!+?io8V@_Ce6{xxFfD_3kg z>Grm0L!B>knCEW8vgesF^N@~a5pt&P_PuK{xxkryPxfN&)KfQ=)XNQG3ar`H%rZCl zsHM{g4;i&IVm?@3JX!Yn8oIll^|ZodwuRaZSlIr!LanOW8Lz3UTDBBq zU-J_e+9bmEHOq};Q$j`dW0*>d-Abk-y`X-)LEb7a#-+5Jwqvy+?PQeP#Jh@S*4{R! z?^D_-d)*{bVJCijUz%^4llImYM9UlHK6~{P#ekw;DzXX?Qxo2!f-0b-5Wp&pdKZ4Mfe=_} zpIkwuJk_))>t^6@<{z$}AbyD1Ynkm^J5x03!EXFGW2SA$lI2xItUV1chraHssJo9o ztEQ-FJ$syAL}|)Y6KOXIb%6PxXQv^hCP#F+BSoHxEihhk5O1b`o!7y^?#A5gn)#DS zDTee5S)e!Ps2EO>5T2b4RA;rZ;ke(($Uj>}^EfKRu2U|Bd^{k){>}4c`2q6@uGHcB zUY`C4_h4Ol$mvTbZB8#|r6h%riX}e^iV`IWrqK`$rn;l4PqP&r@mLBCSA1{A_QH7L z+y3I~%~Ztgsig(;@hs(rLL|8uRg^SWQ!ukmm&LO7=xZUv>%l{tZqZxmr?&;UED$6Z z({G!5bMr;Fr;iSN?Yn%sh52Gs9tuFNBBCLAu0d9>Y) zuu;ozxpHNm<7~jRXaN9fZK2TqA)&J}WilzmhpFAS3|12nuQ);}>2x#($?ANsVds%W^Yk&~$7TDt|1uujEK{7}T>iZQXl%od< zYiEfBfaINVxi-GI0O{E|OFLui{t*0G#z669$zKz92v86X1p`4p(s&pY4*&Ngen`*H zI8i6#D1B)^&F4n#n(_0j4q}11O%^kOIiDMxT_d!_Eal)*)401L1VZiwf-U`mg3$wm z4+Ps^+K&!vzN&iq#I9?!g!*lI`rEetSJoZ&Nsja@T z)2Ba(_KL;xT{-+Gva{Agnw z&^!2%@g+jbfx#2cPpjTQ_1Z z^O>1Gw(q)6CwB+JVzgSs$Hgo1*a}KvWLj6c=G~XE&p6#qVNFlBb0B>KJxmi?*Enx^ zI|aF4@ib^1)kYL~?GfvfSn5pbP!fnbw}8>&8>bWVFRjHnUy#1ue43;aRc|ex_u@{F zwAsWu)4cE2!>4t{k00$zc!zZew+)(^YHCP!?g=GSS!`8=cNvFj_U1qciAlW{&&#M^ zn~|H8;7SdGrygKEw_j~VNlE*3P&1f)E?VQyV=|Lh<{9EES(CUb^x8KsapD}Ewo5~4 zc8Yz{xx0}1x@>dKA==$*2Kfc%JQ&@*Ykt~@kGzpFCrYAe?g5LFX;GD37k zDh7`qm19M>2g1_PB3zSkK!HGelh2qmSn_gEP8>izAS;;+!e}B z-B{PqwcrYKHO!*Psj00s^5Neo=3R<5@76^0q_Gba-0Q*k1T)z+z?%xq*p&Jkn`Mc7 z$XwwUR4*Ge+VHK{%AFIfR$`s?B%GQ{OUse7r)NWO)<^cnM~-ZeNu)_CoMBoyTV-MW zUVNw@`L^)|T#iwq*r|^myyP?{v;RDC-Rm}-TcF&tEK;#BIwP#KJ1aOldS2}M$g-xD z10`lp>#5Avk<;){)7NdyydDS5khp;`NNl~0kqVKYxR#YsmY+Ojih+`W3<1I_iUU}j$7(~V-6S}9Kf9dIU{RS1`LG5g3y)Li0&t2JB)iX3PnSL*)y>sHyieu1~0%cDwvx7_$P(E2^ z`n`GkJ!eCOvSGVj#;(_|kOOjE)`w4`8dL0^DA(+wt^E@m4B{P9EBJ5B3FnwwL{@tU z9Uj`%y?8m8w5sCGqQ`Z2Pvf!3s{txya%AnrXWQf+3LK4$EF&Y!_MdIp)Y{&~c+9`& z?l-GEA77ZERQrJZOWb7E!l8AUMAcCv!QmB`nVM6&)20ojFX&!E5l;&|cb%vUC)&aX zNpuSBhv;>9Ji^^A>PL~Qxwq>=>A#Nfh15+gV+EHDgC}hB!e+AMZlAr&EfYOFrbay` zT2@}}>Fc~dCg5RfRr@ff{;41B67X3AoHg*2$?NmUR>^j&+CEy?J2aJprkZOpDMRkh zHOtca#d9i4;^|!KHw>675-7Y$Teoh@nmsgmZlXVqLU(OUA$Owv(`(&Q} zm^xCaVa9RJVC2JxclV$3SLjX+Rd`DYlvPF!>+5b8MHRU@XTKd)`zGA#$jiKHW3x4;P|KMbp}}rzNBc>yMg(KNw+3Pqjbs zvD8ttw467raIok^z($52PH(Q-_9lva_IV+0`YkYLx_7g5VVM+B?RipOF?5iGYq%zx zDcgzsWi5XX$;j%0Nz$kOTVXBmoKrFSOIMR;L)ams&=yr0)vf5AV4`&lq1ao|Ydtsn z{j2BQYS&kE*!$qTIUypWnKLRI)d$LA?;=i8f9gxvqh!9D)EF4`t{^Pp3F}^nU62^QEpk6y$ji1cTjH2n$sID5_DPqENr)+4Z?gd!eCM~vDQgx(mPi6Rz{|aQq=)p$1zy=Mo1aM2zcypgQbW7( z-YPSyoF(zo?J51YdV6ozrEX(ND5ox^s()C%o~@tuhGaWq@IpsEQoF?lj&^wKU^txf zG-b*sD-q41opq18hd*FF!*|dzxd)~#Z0eVT~nH2#^#H+Dn zfGNl8F>ktQFv%OJq=fOp?07S`*1~|TnlTm3k}frGMQzgHATSl)*i8x4c5Hl1$1*=@3an0;QF%AiGc5h`_C;o z-?-R29(~sI+mbW0-p;;vUGbVHKn);;@al{`*Sy{YdFJ~v)-pQ&OUn7^_#K`r-`=P* z>+D1{QHSDoee`GhFtcCcNP9!)4WyX#b04ru>B7B$s;t^@s<3apEw8@$i&yr>^|n}K z2G(EjGMp{+PW8R^U@DC3#z4a6Xyp~-RmP~vS+DG~wH_IFYH2-&-*u)xEdNSfzv}v| z__b`hUcf{&3t*h>{Do({;=+XE@Gd7r#irr|w<01bKr6kq<9bdKOy@(J^%Z+s)=8`6 z*vpQOEpwXK0hGL6wQP?{lPGz#_2zH+J9fk*ouAMzD_5U==~7JIe4naVx8S`TitDmi z#iO(D04P8npjBDFu)HZlK+kHHAT-;a&qkv_BWp%aKfhf2r3m$Ix;{;qc&HB@J@3L| zNXLZwLdXm$q~Z%HE1#BrN7A``_A5*VO>qW(6^((rmDvlvp(qJ#!OdYS0M8LiLkTGD>VVdQNxG6$Xkq27PD-}R5=;CSb<))o z<_n+0TNadsMaRZj0+oeTwNtXd{%Nu?pIe?+gfTBQjy};49lmPF-NpeNBI#Y$SkYu) ziPU75eaC%XAH}jJd z4;ZrIiug{IE?){JT3;xDy^|kk#O1c6;h2v_^*VcsEYbVVkOfGB>@m|o=f!o z0E$rVP$l|s?Q%@<7M5Wse2v}sB|Sa669CD_LLaOVN=5V%Ak9agYwq4ScdI8@tn8*O z_*^7tt=8AJ_al6qqbaUV*VD0(XuMU5O-Qf5y6oB) zrY)qz-^Bj<8ACO@U}P-{0IyOo7!bTFW#J0&59}^_BH?`cM4t$#-vQRR_;oPxp|i(o z4Ey~PK1~ct+7*+bwY+T9w)CG389#{e)pGBnCg^WzEY)333Q2^E3iM%MK)WpngWzQn zcH4!9J=vk6M1Q4?Qy{Vzhq*d|HH{A%*OkAimt?99+#78#lZ#17 zr9k1pF2T{PH}oI;_B;Lcw?bJ~Sq?A3*UQjf>tz`=O-(snUOALKQr8`UbjAQcI90?A z3>M|2>}-t&;u%3Ll#Ly(guemgmd25PC>|i_x|kw zeg?yTtp0J8`k&SRKUnie(GU8GlwS!5!lT0NMj)NBc#Iev{RhRnPz%rbX`^+V?T%?W z=yzK3m+b<)1;0c3#l~Zs)sap(>hU))xG;7^+F)?(;&<1`d?z0HAz)nR{DQ(TAVfq| z5Jw!sV0awTc!*e_C=?g}-|=FB{7{%Mo||=1LfP5a;`|H%>HqwSBSvwQt(~Q`vyCGP zhZBUrjiE073*JT?4T&5192b&(vaiG`aZ0Gvcw=+X*^&{BoJ~OLDJCwsD|72 z`BM${AJxD(A{VcS|CE&c#nzvu;sX3n2mCVs{3*n9**^ze4Ge^Q4^)sE1PH;Kgm)*- z@E;+qh8xB2VFOabjpYv>TulfFIi{R{>Fc+&!I_97nYjXoaZ(uqn&Q=?{SW~2&My^~;VKg>YH$DN21%&+r)?Y&B$7zZG z$AN?W7falqST*|aa68@+#skxu^KP44ySR$F5}c^AJay_H!2S}_|3_ej{yoTkfF-nm zNgzUv1x%=jFS$LB`{C89hyMul*T?LCdmI3NJ`P|3VW=oXSO@|Y6#n^K{6%*Bl;Gyl zADg+txcTzm&SU)aGa-$&cRrxnxF+A*S|KUSIv>#Ht&k58RU)hbQxg%J#LY1aknv!< zzeh@GE=}Vad6<1;qLE2J#i9k(zY&(J@% z^r62Fo-FQU3x2)lRzqT49MM=uI}4x(Oh7~c!Uwd)VqGv|Adu4^mjuvmHaq~3h8x<- z-4b_D=GVJitgL|+NJ|G?FF#tqr5VS~+o7H1@W+a{<;0+1C=4tN0fR-LV2F?*58%(4 z+sh4Q4FCh7Z~*v^7f@J82qpxy2L2(#&)4`D(D|oK6u->=O(r5Dgq!XEswW~MiZlFg zGEv+Z{U#H}We$JWgX2<;zskU1VcgvEHyP}AEV%PYxXAjO9u)kW3D_{I9%vAJ4C^_Wae*rFeq+D{+mohP~^8hL?HMa;;(&(z+k`i zD~vy=^*24(Kln;S1pFHoVL13VdvSTzFJq2%L*f!9x8nnG2s>{SE{1Sw1DAR#FsNJ_^5Lo?J!3Mx2&(juYK-CYt=ihv-U z(jlOTNSFA{pdRsf-tWBE^?(0xF?-LmSKLqRwVt)^#jYeN%>(7-1F&ZggR&|BP!I%U zYh(!!5(0tMT1wzf3`ftAo^7)KC{P(TGFA_Bl*O^5|i2P#P0VsRk&egUxN z4I@j8F%HE4{il=*?wTqNjl+QWz6+GlI2^_S3qlZo0>G-~XcG&p83_5~se`StDh3DA zA#^J#O@M-N!GXZCHUtRbKdur#uCgG#18|^!DnP_dMDKthp!*IVtb%d0z2#s`(1(bh z(7yu4!~!jD>q6)eLij_%5xjgT5F7^OMG@KuOAs_8RCfdke8(q-#o7{nL5XD#T7&rb zr}?g9ux2=O5cEfv(iYYPg+X9xYl0OdF~+tg7$R;*oC5}J18|A1*4D9Q;-^?#*#(gJ zzj8Xy{n694xZCC~Daq5ut8taNQ%HA4HpRlNogLYv69`AsAiZq8+KlE2r3K^PyIHjgtLfcdrdOyMAfVaiYaNnw{yBvHZUw>|qWMb~Dl^w{1;#okLLV#UGl%x|{ zPQlKVhmk1wbIQqYShn@N)~|B6jZ9QT! z1v$iYzslwt2H-FDOcN?6+9rH7@4Z5Xp%Tj~54rg0y_A+DWpLo3pq&>=K&m5rLWOx6 za`h}mB+oJvIXF|eS^aKucs#zRDWiGBBb_o*V`2B2dM0JZ%To=aoToEZcRx*@j~i_G zTBdfBzNLjjy0Wz7o@}IH8#8twZ-Gs9A#KQ)%IIv&5(%ekTO-=2Z0*M9)Ut){Y*Utb z#D=6D?kYRE+H~yT5tnc#N?o;gVO`&n)>I7rE7styJ=>QBbjFU9We49QSI&uS$5c1p zbY3yrF8``tit3Oo6AGDg;pA@rBIt#sxy%zEp6GI}ER0wV z3r~uN#pul?>hN-=s9w>jfQ$<(aG6

jJRKGmzVoPPZb{wpT~n8XCSH-r4xtA6!%9 zJN9DNwS8}|SZR*Y&yR$KEFp(2!{JDVtS}|kqFE6YA>VXzV~01qnV8xmFLTDkoqoOh7?7Pl_;1| zS{d=OpwBQWJ4|#b28dM=VXh-7%{s(3PCsypaeVtIq_z+# z<#|L}+r|e@@>-g4fYR4@i!AYQat-2Bb;GhV{*w5p>0M^0F8xxYqlnvW+(~S`FU2Chscmpv#W2u z#OJecS``9j6-iq#*PP^uzdp9m?<6z)~AhrdZ}DFYf@mDXBx zZ&GB)HHQkYW1+yunnT9Q30PJw$-pMI;g?j87gW#OId^|p2q_bNrJz@FOGx&5gSW>K z0p8hYCMpx2Gj!CnVojrLY*Dl_U)kMG4oTaP9d?7v_7#7gQ+`lA2U8gs{lMvPs1_NC zm}U%qwP|=Xde3^u)qp&tneCL1q>Mf?4H$|} zlRkEDDVeqJWOjPV26#sr_6|F#X$>qNERxJNOp2p;HvTT+p82sjpVCrytOdFEmtpGX zIf3`0br>^`1yJ}q`e#gyxM1y3^}zK*4DS-InZgGQu8g4KO2mTRnmx?2lx=8}hBTs0 z2$=ecH~Q8|QYAx79uJN>m1X9b!V`Kft2@(54E32B2g`sfPf;wUskJnv(Cf^{l2C{D z1=E>ym)%js+>ovHXjG%F!9C*>o>+!z19hA_tdui#yNn5zg|y46dFnz*qQ0ew8lLhh8`B#%|;qO-+mPPX3)|P3yKa z-CqD7ppKlXFJMS&Iw?uH7qx+UMOPCv&AcJB={OsGO~7k~`w9XltEu#qo=|r68@;-P zqjqHJNnxc@35@H~T}Tdx$u_9=(8na7x^}nVQ8>k?s;2U$P;nZOcbh{eQDYg89cv+TL3rmSPh4lde7q8_b)RdH^vSm-Gqx!G zi+5BYVE&}7D26a~zLHvGmOek<5IPO&Y!2-JN@!6shux=DJbJf(+rFkK)w z&{LN&G|(w%s<;1L(awfh&E9%`&}0&YS{CHoGv9|1A!IzI-SqaIeV4w9&z4zUYeo%V zl%120xkLj>nrA!T%HQHQ)h{t)kSqvrleKwkOL$ktSd~mh4Ae`&4e}?RxM<&cVx>mIAw?5(5KCOy!(tDE- z)6^d+){lgBKOZCJXfU_{>}M9cpU4q~Iv~BjWCxSE@44`Pf(ur?WrW*Ljfp}i2rQ0v z#C(4ugRyqP;4F;M0I(F6kl_(CTCj!%Rt)QC@t5FN?hGU5!oR1BP!Jyq1_6P8B#&?y z3Png6|0Q+o)$q^_SC9P`GrJS*?pnE|TOQwZly`EC$$)p#-IcwypY|wIJ|tH^E8}V%|BTwg!Q#*wV}KVtlawQ zSH*nOqR|Uxx_8=p7S7hGs#wuGLth}lR>^6oIWtwiVv0upi15vpONz9VXo{(5j8&%Y z>ebyNjlQlym$?n}3oTop(n&soGU+U4adU9-7n;B*bo8rom)tsHcg~KzrZ5H4ZSIP> z+V)Z7t7@l={iD!31tnfzFpY;F%4ISa2UEpS;mM$ioV+^kyKN3l)tL&hzaW3JRuZ8e zP;Dxd^5T(~n8EOub5pn1(@Ltc3p00w-F%vmjXehX%1R>5+la7IqxAy6R$aVudlHoN zD7njf2608Xamf*3j%Qw|XS+D(jh6KQQ8D)>Dtd#@SxY=A=M1D|FZFWgED2vlyt$nc zK758w&8{XlG0HOH%wuSERiYt#FYT6`R%*K8CC8iFavo}`3tWy*Jm{=Azo^qGE6mG< zsg@3Fh$HB-Rb~{+J({d`~F2aIwQ**%S`;(OS|O)*2clg&PqG{Ra;flI&BZP*N&%7s;I2gapzgh=9&#OY*SW!8_m|0{^YHryZ1SZ8dQCH z$W~TVcYO8rXBG&@w|*-|SrPSBY^!v7hRr-U=0IyKFa;Jl*RPU95vuT7>-CWdN}6n- zlUc5(u0cHi$GCYOKE=Eqoz>gbD#?=q&t;e=oJmI~qob1~ErI7%*{dJ6hd%6IJt-V5 zB7NfAJWZ*Q=?9_SPV`Xi3zXzp;cS}@AY|5NP<*F6{ELe}ijz0rIq%`MjKEl*+_re{ z#K0-R8~t<2CRV2%w^d5S*T32H_13R!D5t!&QobM3>;FLq7&~Sb-HNA zTF}~}6qVg<{i=0<%3iuy$4T|DUaf~Fe$21UtsW3!czV~uC1aW2i3Vyhmnljp?o+v;x-0-Id& zxGu|3K|ZktJ?XIbvGcaeZ`BPo^xlvD(skeHL41Ti>*xyChpp_lg5*qb!PLE4FM+J;SWDLam+^ z@VHJQlMIa>K6gUw?O9a4sOyPXly_s&;CQ^PRLI}bMJamhLhV_m{{A`3 z&*tY98fSu>rao|X8Wb^vX2i-=CY)Lh8Hu0XGtCn&{Z>n|cg1eJ;@HhG{hHhtbagP* zl62=S8>)=qM!z01^$g2ip!y{zzgtGt1L(zM|0+CirJwtL)#x0KZ%*5L*gVB&JYLeD z<}s&uVBequ)u2FLe!lZ;4JX|0{!16mEmu=XZhyTX0*#Fw<`z+8doMzt|v(TwVE z_1+(K9CMGoE_OFozh-ParCnfU)T|2c?@Jq7TQqME=l|^fLP-DXy`-`BwcP1Ba@FU~ zN2IRdd&oHYDiY5n+MKGZV{1U+`Q&4l?H+a;Q}2 zG{>s_LrT=8m-!dy^(Ol&=u>y9D_=pJPeeAM+-&4F_PA?MfeK5I(;dfN*q^QW@ zHbsbtFF2oSaP)D0NRp}U@qGGv=VUjR!R^_YGqa-4c;21srJPJOLnITGS{v_z6Xp< zcS*Ec`$QhI(%@(-+Pf9%CO>|iJtuVRbyTNsd%J(tvkk|b)1w!kDSn*0k*FEnO|}u+ z!_t(BR(olNvb7qr((X$ti5hi}54UB%eWJr#%SCP6)3D3Sh<>eO_Z6-4MprpLZ%kbN z1K0cYE}#hd#5}KvYRh0GK>xy9X?iQ)Y|TFJrc-t}CP%VR^OfR5dV%=$33r+O-<0-r@()+n+l%TtY9{H{$-{#V_6=bwYHha z{3&Krg2OX!X-iU9_O%%x&TXlAhI>m^n73$rhFf=gM8-9PriS5xKcGf^bHMwK^LUcm z?ewK*GP^nmPY=Mi%q0^4J4%72ee;Dm=W@F3Cp7Grz3THOmtNGn1HNT1-2m{cxoq6_ zx~(yBn{@Qccyv7&`ECXr?ZQQ7M)#JpDr3o~-U5F|%|&nGJgvSeDrG5?DX*tuh6~Wf zaiiH3AI7mf-K>h*^7EXW#k#V#zYC<%|2m6h)Y#l{tIA$-1}FeTRb85c&oq3ghnC&0 z3pNf6U5;W14BfnRP7pq>^BlI8h3^RnE>z3Gq99#2_Z?}p;~QJ3)ZeBIAk3b1-t^9 zT7OB3fUAFOG`(U;%RFKd8GPBg&^W1{4RD&vrSg1cZp7(JY8q3%p4Lr45e&ncdHISH zb#~dO8lF;S-%S4?iQ%{`Sdd9G1Hb@M0Iy^4{+``))t1*E_SI*>&3{3 z;xmdS)T0vZW|=~l70DN)7+F61y_}Xs3Jktux+jagt`-#!@r;%T`uwuIz=v_RcA!{E zpzo?SXX6D>FIoGX(!4S~(?ex8i5X4?X&)m=xqL=6h@HMcm>$`~0BCL|ptlm9@^BqM zj2oD2c&m2O_pP^J-d%IZnTNKkK0PX+lObN_z`eFBFY{~gzI#IyyLmTu?~qgsM=1We zbb}GOh2PgpAcE{)*GI;N@lZpwA;!?y&}`gr{Kz2^_#w`JXr4$u{L#F?zqhZaBy8IN zq8!n4P^HpZU3^zXjqCxQ_u8_Gg|WvE zb?}2bt>CrqS9-$Juuh9XY)=ol*VD_W6^!63xz1CW13zn@{V2#?$+?3W2Kp+^R$Y#` zAC3~>?Qn#HEY_j)e3!}C%%^L%C3>^MJ!Mvpflt2JOIE*EQJYZvMfR&=PMkv5g?DTSqcr&`TNWM+D?Jt>sUs1#Uvbch> zvgA!JNsJ}><}Fn;))4?E6jgO~#9?e?v8J{lA`PX2F|#0a=nCQ#BQQ>wOCazK2NR3~ zac#{hYeHaUEO4#_q3SI=J8O&$k>r68i4`!hM@fvMv4e#j&ej1$SXC3b8n6Zkw$C{c zNF7;8HQQ^lk_u=$Vi^6-iIhhM1SX;)>_(um zI3h+z0_U`ELKPy@q-Lv*wb&BZ1TU zZW{6LY!?p{Lg<`_4+#fB`33k0bQK&<#34q6hyw}02=V_NFAl^5gCmKApq&iH!pxjt zX8>69=PiMaBk+V4#$s4AYYYJ=Se4+zo5UNUj)WZyg6H@5I|wdNK)YyIm=L%zB%!?n z`Vsv?)K7=72|_Rm@##PP>;2lJIXECl!$8m<^qe#lwC}%z)ZD?n7BT34WPNw*FKQAj zAw~pjj0QpXBS;MPABz#TeSQ^#|Honw0)0pg`- z1qcZGJy5|4P!N=;649Il#eamf0>O*l!v?HC@Z}HkRRIBl?(>`n`r2>jXS?4G@sqOs zwZSEA>tI6&rJs=kA8wWx4@y0faW75{+0;&9>-5m|PDnsSb{NmU0Z+>8618oZs_p+^Y5aI+~B zA{CxgX9*keShKcGg+3rLFyYd6Z_h4J+MwDy7tpbJ(=nkHdNOOsuQZn*j(n&-N9rW8@f(etcPXLWTI zbq~RV0Y3kL^+4$Spy>Y}9S8p}rnp~Nl{$!Un`THuLD3B<{)VP@_5$`Khf0l)9s38c z2SWP)2rS~?gX{-bQX{yqDqfdYkMih6hw_jgRxM5YN1z8^v;XaN0Q`C#AiPMJ02GOU z!uXIs-;3X5`)>(hEd8;WizJMf|F)I;)6S&Srf#W#=eiZCZl=-^KBlRFMmOnHfPf5X z1%&GGQN55!M&6T`aBbfsB{!M6_8*LY@NCBarqh4@ivNF%ls~82@8?ax@)jn<8FK$% z$Nmf{VS9@(G3}4gKeqH?2c0KDI8Q;G?>QCFI6G@woVA4!$O+EN&kN-Snd5MFj)GvY z&0mjrZ5_-m0l-QQwkEfX3CA-I*0M7(1sS1@tq8sRXn~Ms>^E;=ie)fM6&9SJ6*R%J&_q{n)kTU!b0XTp&cN~~g0e}F(KnGK6 zz}2fjkcNjN8VHgy!J61QSO7sPCKhN65Q;0H1{42ExA^R7|i~w6i@>5dRebQnxfQv$D4U3jKKM?0`~7V}bg( zZjmxLC}?*q5F~GhgCP0iQ|ia3JkanLIFR2Rz~jcFcShsTeTNTHLt`9VoKZM`@c424 zE1}J-Oe7uLaXo@@|AgQ$0TCb!CL#cbL2(^`q;Rg`>SKT+-vLV4+dJUCLGXot4F~@5 z&-mRy+go5Qfsh}4%2?UrJO+YfY;j>gqEQZJXgqKX)){SL2XK#X*6XmJkfH8+Y9wJy zKg&0`oWH!#?|g}vkRb>~Flt7_U5tt_i{Q67_=4lEPmW5ppn2x~&d0z?7?kDrZuyTf; z`!+eZk1!0kC>Cxyy<>gd6ZlAp2?Y;Fo@{k>ff-Rnud~HI9?drwfwz13xfm;5LTN@` zZkx&#riUVg_LweTdLtEZHfs~T8+7!^-JG4vi{^6XM&VlAfxF8U1A~y1mc5T6{_7hN z(+9G`)M2p&fn1a2pIa4mNJ3)GqS3Mhgc6<`2?>XDWTUi(&Wvsrv)PBxP^bD`c}mUg zT7ke=sUeHxrj}C?zDg8itb=}p&vfJ;?=FU{X;FP{kIYTyO?mDY;(j5TUd)wtnsVt~ z_Vg=j3r5$;pL2POzzd(gOq@^DD84%m89(iFu z$R&C{KO}$_0=(9&;jJw#6~a(NCg5}v3s{0*GRve?Sbb_KM@2RIB*D$cpGmFhKL6=6 zHRN~Q- zd;i-)<@%?u>r2-@x7<8mBNxsXg%S^cksBB(dydoUK~jFJQR@yz*fsu_Oz##HO3$R9 zMte=zYcO(3gw^r9+D_)sS<0E7-*uvPO-hO)9^U*aT|AZe;HYqgr}^ICo(|*a)&oA# z13P-m!(46;*Df=_Sjp&exOM3k*;g&h1Ft+1lA8LXB=V)tf(Ca(-_20zcR8|-3C7o; zpySH{L;=x~&p2`)?Lj`ZyrWNEjy#=rR!Tra&gql}*(K^U;_c^fH6l?S*sw_sjiz#? z)+4h*0v^FP&J#S+GXl@Y1melLsW&_%e1gITPe=o1lDH|t2Ja|4hu`3HoGmP*O|iV+ zv~VwN!GD-aNl|Wx9kE;*z|EAw5NI1AnpvNW}CNi8H?J)IZVqJnemnoY)_rRI*7)s&gUV)Od zWQNq|=(t%`F2+<*`&jEIM}AWPc`V<6(z9G0lwc&lc<5((w~LMl*B&jb?nkVDdG~H* z{T0_Mw_2at!EYq#sQh*Y!OQs zg!^%X-1DKO6djvI7CTwrk%6I8Ud}a*Y7DHTJ>H2^G$R>`UrwWv^vqoyWL6BcjYYIv zn9&@O9Ui*TE~$;VaFr~Z!jMVnar3aGOWoz!HO%=(+pk$*NY1#yqRe{lP)Oq zxgR!!U-Py+xD%+O!;LH>xMebx-B!|B|G5waeN=S+kq7e8qepM0Hy>xt(WgB>sZPDo zNj_R`YZe^rbMjqqdo-^~)UHIaVv}51?VR8!XEfz?0khHfG=O_6;QFuEO(H6z;+2rz z7bu*1i9L+Z!kS4BF0mUbZp)6v`7Qt#sOw|LCgx}$vuEu)%jml`J1<62*+A4Gv(v4o z%1*zFbLtOse1D&GJW*}!<;TUys4I5yFJj0UufkF4--OIA&g;A&r~)uj)R4y#5i@EN z@4;DhD#FeLqTE={JTaG0P;7gRVxOH-Q#nzsKgC+%%CpHz>VrYfBX}5#EIDTC+bKPh zs>q%`NT^4p)u#;DGIyRB||L_@qC6z(4Y!$Tst|(g6NcQ&l)F)=^&^~ert42 z&}!7eAWejSEa=;g3xi|v@~kRHc;F2!uO`hwWBS%eqz9{@+$VvzW6UebcWJv>K9%)G zJ|OA^+NTiL$I^7@_FuMM^EP-qmYJ0$QES#~hk1`AqfQTYmobp-u2F4ytU4Suu*wiV z;dIgYDP23ixSZ^EP1!ewDBEpxU|#j|4VF_xRdKO9Z8m*zv2pwruc^1&p7oj#*~>S# zE-Du=y}KVzPx*O^d-~!PQ)G$?;B)&e>2T7*tmUS;0ju^k9({(x==icNZE5BB{WGK@ z#T|0)FPj;(d=YGjx92YR8mrrb`=u2Jg0g3b4egbk56jN5AYej7N`sdi(@yFKKCz@h z@F}?{+tVO!?KcpPOq^6UBU1PGluRQc@pH_Glp4HS;t;)cUdw4ot?N^YOSIe3<0E5-m$&k~tVxxqE6cD(oXS_Hvg+KK5r?A-F8E&-f-QV6C9>{3CUkqS;Qbvj~6 zeugr5f}#`1DY?_=#zG$3e%s}1Ltj3rI!Q(51roWP(P!b!BwQ|tF|k!WXa`SO#A2qt zia&?b!>PUZS9oN+J%={*3UneM^8{vT%$sL8=hAybv!26&K~a2u->k?Is&empzHd&y z5WvR0r6m0|2)(e?w9#Pyjg{0u##azi`OTWx_u58q*T%?`8n>N2^~9Q@J^7j~-G^Te z=6isg0hSj<^ll7%Z8x2AJ$r{Ca*wDQ_HdGr7^ygKEDNE73157t@S4f|L@J%Q zV5x?j_pditpIGYh7hDUw$@CRqW*i@LKX?+e z$}n`UJ2-MZGF<5sH*2pbYsJjnhb$cJgO2`RQ;S%@%qJ{v)X1G^2vCwvt0L_Ya5GlJ zRumAvrN0ji)1#E9Q8hcYUvwYBVZNtn|2Y&nAJk@=|3HCpM)!&QIl+aY%mkr!O80k?CyO)tOT9XE7^Z(|V>0Ds~7_%dmTI z?Q4-#wv}49R8qO6O=KT(QKXN^@YeaOUmdqMn?vWr>f0N;)_12run=B6&$&dYbBCUg z)&2fJqX&#TmOf6ENVrQ(^&6M*Xe}|kaTvrL!JvJA!*)E>Z`h~JqepBdgx9@*npA!8 z1QX}y;X00Z@Jnev5gDilnQ`K)ILKz+oq-m!9?iu!>PMbOdmmRPN0JH-s~q|QSx&M* zvk<8R#D;gwd&#}OL%PtcnwNHRFfjqpyf4gfhox%rUnPw?2GqTq!Z~J;F}L zQ7}<_)};}B!t&TFrGDVf=6oqJn+eb^C$9Qt3}-?>*KXw;R@TJ|kh^e)2El7=(Yh69 z;w=Cb;*KGFRyE*tk6Oi__nhz6%tA?0l2~;uI|b8qayz-6mJ)HXy>8~>=&;&}wi3P+ zG%Be&>Sm>WeluSQF`Mm;1aGhRJ|YJc28-TkJX`v)(f`4lj#&YoDZs!m#7{DHOegS0 zeW2kVwqGg5cS?55vq0)Drr2YKhBrchAW0Jp`uh_(w5=-|YlSiafTZnlJOfXxK-yOJ z680FYKMa3TI4GWy{gt#pfN%s93*eLSTlpeGDFJCLSd$e2w?=s9ZC6 zo!oXxU}lTeNMOdxgR^sl_7rO&IR94UBVhtTmn?Ww9~>UmKlmKpT5tV!SoKZW%TlY( zw|P`!2?=8@eQ(U$tYd8HmkMha?uC~nO^klC5&y!Hi1D4A+)J2T5$O?$1g6NXVx5(G z;#`HLRZmATbdSd^J^4}$9q!caLiiQgcn&vgN(5%cn|!n|@a-A=$XKtgX2akHsSyI% zq-7!&E!2Zb$y-8W9`C;4QKqFdA)k#$+q^K?ynb-9CD0@MGM~|{V(ZSQbjXJgR{hl+ zJ}zG2VlybY{;jI~HP7C}uZ)wexqc#6dR1GA*E!W42sjO*Dw#Ipme+s>Qq z2iGLL+Nc{GUPQ$S_KPApO=G-GlbybQn=Me3l zf^J5ZF%L#-U%^L1{Ua~ti4UC(_qryXs?w4|w0haNwxl3kj-qbyi$bi(j&#Q1XAf+S zQEfW!Bl+mYwtZD#p;Ej}ccASG6?92IiCKqstN-j0Nc=+lR{maxbLnf@;e%@V$&^{4 z!x??Y<|He-t9@Id8C;X`qH(FD<&2OW&)09|AEItN_F}xWc`##?r4njJ_M9FlHv<3m z;lX>Z633@WRq&90KJt0WueqEvYU07G5e{>7)dkVq#!gTUs=BJ$&N(NTlU_1)YDHzG zz8C*yF7HB^ahIxkcRWXb){}0GmmiZ=EutYSaxW)tAi4U+Gb=$%chDEpoS23xj!im4 z<92>5TbQjqeL6IDaYQYZJW8omxAo*SB~329t40281EXZ&m82zpxN^au{-$@eTH1_A zxg6WH8{zwz`1n+$HT`*Y&gzh!sF0COQn7e(nX^nwG-amd%U6f`OvdVJ5J*O`T)SR+ z@Pgf_iVE*LVCp9UT(c!mnzL;_Ao8*%e%KyVtGz&X|z5iT-R%9 zx4DX`y&Z+hr@2yUGkA}bNz#8`vs+MPmsb(nZyhBHmuNJUiT;qdb#8$WWR`+>&9#qe@hxA_awoZr=7^M+ICh%_=if zt6%!iE&yNEBG~SpHtb-IHH)=c)$mfoKBO)gyrsGp9yjFjTD2g)?`mpEUKE{U^`5i*fyW zZN?HV45i9m;nO<1o;eqmFB0FPF)4N}yZWfXZ$%%If4a5Q3#BQGLe1(G*_gJg!$yWP zC%0BDdmama_Nuvh>)YMb$)2tJxkVE7a<`Mxvi^g_T*DP9OeuC`^_BeH#3QS7hB2S| z0t1>5si(tr7Ouxm-{*k5g*M%gys;g&>qoSXAru`GQRu$Yce{MnxpI9;lcN{Gn|fdP zZPJwDX8D1<=zQ==s!zSq`xGpXV(RWbn9m9bE@hi3TLYs<*tZfZiswGjjn?vceEX!G z=)2SuO+q1-u;nQ|Up{_Q`t7VESK`E8-}#AESgP2Ti{MQ*UHx0-CUteQ0wZ5RM{9BA z4SR>F=RXLhM}-M_&ia!H5!x=@SF!P4gN)g>sTF!~{i06K!uQ_(@wyre~LxVJ7*bR`V4tmlVWaFd+{a^Lr)oBa_4; zGCALyRVNMIvT53}DHLUTkSCOPS7@wEpMq=CDTETi(^Pno!Ek1{f+6E;b!9Wy?QCot z!fR-}?gROUjjR%}q2QS22 zk>hN{^lk;4QTh6OS@wpaf6mr!3frfIT`8{H1#5dq1Nl}9K$7QL`#j&CyqG}A)I6WT z{)C)IHcc&aa44WwbN8*EuiI3rr+3!cGr0qO!P`E7qZexgp}s0%Wy4Fwc}#f&PSe^> z8}}LtX4YyNyZ}eJYc~P>TkbpF_q?^Iy$Rp1PsKNYgx<}A;@x?PE$F(rtFqSu8m#<% zHQWuS&(q#gN2IU4U@aJ|nCAs_aoub;_mAe;>JPS+MuG(DN>g=GM0bdlv28 zubx%8YikW`s-t`fvu&9kV=CG(;o-5x5lvy-)gBz&)7dV`Brh75d z8<8YE{1@wu-U`p( z2XJ}xM{m6?xni)&_+Vn%J%y&yHSu93t?Tf7dqQU67pm%2r&qZhQVH6=<6*3TcjuYe zU-4cQB7BGFv{NtIl6~%+Lv#($OmA+xo*DzwTxl`CVol37VHO*4*|r#!+Q0#z;B~J& z{~|wzf=5GpHt@D>TX+ofxK2T#@^rmpE?MJK%3Q6iWh9#GvS`r@nt1>kkPc{;*U2ty zNEFaEni+)TkGx+Dp)(4!G*?MMuv&_u+oqxbocnDH2H01_>LV znoe8HxeSggOu7w`x;{m9clSzC=DhtoRXWw3O1s*xHfNY1cg;V$WLh&W#c_c(YD1Z1HI9Y-b5PTqypYJ~JJ!4M zLN_$xlEJs*rNTcqy)Fu1S*UwksvkIxndK(6v!qVEHc`*Zut(FbW1Vsf{! z3`0R{90v9D^c;2o6FydYKNWvUqI!S?AAOp!OWjOhx1VUi9ZT@J5QoixK{X(0%h$g|+^HhhyXi1vd|T2`a{8lz*pgP`t$TSH1+q+5VLup^TFu#wNySW0bMQl=0Nb z69ljm-2c!#UIY8Bd69o_-%v%&p%F+qu}3F-NecNf?U}y@XJ}xWW`eRN32C4|Em4E} zS}o{&u>RIXchS}A%GN%0FZ(d^>yy=Vti&o~auLx9)z=rDdIK~B<@g&oI$kl9bHGC? z(Evo5jBY>t`ZZH0!0o$TIi+IuXHN7AgZgY>bsxSAKF+jvT@B}Wdcv!LK~AG+!oQOD zJe4K=XFbLhQNBvDfK@peYkbjbX&Zl$E%|(+QiP$Ft0=)yMK@1XxbC{4{`fl z`uiJEmXb%}EqJ~R{gp3EDyga>wRn+eYZEOObrX9G0E8>5?t#Ig?d0vv9e{W>R1Ixm zg`@BuKyC?~@QLODf^IsSp`G#Enp@rsrwv+RJ#a>K7e_~1v>je+1mopB5WYtw8iR7S za>P0~197YxuNZ=~fzV^=6DKXoBQ+dk<&jDzj`%eCtDXqOi-$jx;Xkr}98>?3{r`hE ze~^CAPo(^EKoA}k?li*09*f6_!AYM`ddZ&hiroGj%L<#*a$^LR&fcM~cNWb`a z?6b0o9Zq)r4a~9rX@LR4px;9y`CWA7hk$XN^TUN;K!~si94DH>V0au7c!*e_2o#t9 z-|=FB{7{$>UYB;1Lt9x`;^GVd>HPc?Cko@_YAck4y@f3rhZCfZ8$&JpA9x>eCm6Vq zKR)lk4S|x0yS9}XPN5aTwfBpE_;JDer;j@X!372X^q>A4{&`08>x3W!1wwv^#4-@z z@%a5J5dV7CA^|zhtnb76r$P>rlE4E-nE)Zj86*MykHv7uK7SU2{l{Wp0o?Hot|0zX zT>KYbf4YiG@IM3a%lz}F5wGL_9CRfx5b`}yK}rxH1n&|)oH)mSq_h%l6u+kpNC`KV zKkfi12?8OGLIJSeSw9PB>OHaG!`00jI4)?ZTR$4!y{$AN?W7falqSXFxQ zaNFhyqk!>^>7mBvj!q&@1SiT+r%(R_*k4lm{|Kz$zbDxbu!N>CF?D|f0Yl1Dmz-Zm z{)lQ>=05`c^)>t7UI)ORuLD>>2r2>*5`;kELOAs711ff$Qc#^QXXvA_e{x8qptgh;Qx9> z=zsI+zkbF4KW57B%kB4TPas7rGyDp9e81>;g_Lq|!7WV3GxU!medw=)CxyG!gJ18t zl}xaXwhmZZD^s8=Oh8xw!Uwd(VjVG}AduZ3j|3c?EqDMR6=w%C7ZmQ2(66-|&CG$O zCMX+RFF#tqZ8MIWw{oyY;;&S3BSoQLC=4tF0fU91V2Gd|58%(4+ua#$4gdq82mttx zAE1z+AWRTw4*bK0pRe&hK>MFI5jgJ9|8F(~82no~1Q?E6@BUgB0TID%CH`iE;x&)I z+i=VL-)y)paC6IF%Yk9IMfh(v7+e^)6Zu;?DEK$bF!(>mKf31rUMEvfDu+Z;* zh~QS3ztt6ifPeEt1cqM@|Jnx(F7jKy!oslM`VfW*|85gR{MN6Kh|q5~nBec@CM+WO z8x~=(;BWql2;#Ope_+Nso8UG~&c~Ml)vY|yxE#XmgB=|3X@9)rA8(G2)BbpigTb0O TV~^8KL`Xygz{x3nQwH!qovkV9 literal 0 HcmV?d00001 diff --git a/figures/aRowCPP/aRowsketch_cpp_froError.pdf b/figures/aRowCPP/aRowsketch_cpp_froError.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9a38289583859198d77e4e310e85f717c8fee62f GIT binary patch literal 9954 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 literal 0 HcmV?d00001 From dfcbf1b8be0ba2681d31466c536061461af02e3e Mon Sep 17 00:00:00 2001 From: Lutetium-Vanadium Date: Sat, 10 Jun 2023 16:28:53 +0800 Subject: [PATCH 2/3] Add algoDelta configuration for TugOfWar --- include/CPPAlgos/TugOfWarCPPAlgo.h | 12 +++++++----- src/CPPAlgos/TugOfWarCPPAlgo.cpp | 7 +++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/include/CPPAlgos/TugOfWarCPPAlgo.h b/include/CPPAlgos/TugOfWarCPPAlgo.h index 63e1692a..25c155d1 100644 --- a/include/CPPAlgos/TugOfWarCPPAlgo.h +++ b/include/CPPAlgos/TugOfWarCPPAlgo.h @@ -16,22 +16,24 @@ namespace AMMBench { /** * @class TugOfWarCPPAlgo CPPAlgos/TugOfWarCPPAlgo.h * @brief The tug of war class of c++ algoS + * @note parameters + * - algoDelta Double, the delta parameter in this algo, default 0.02 */ class TugOfWarCPPAlgo : public AMMBench::AbstractCPPAlgo { - double delta = 0.2; + double algoDelta = 0.02; public: TugOfWarCPPAlgo() { } - TugOfWarCPPAlgo(double delta) : delta(delta) { - - } - ~TugOfWarCPPAlgo() { } + /** + * @brief set the algo-specfic config related to one algorithm + */ + virtual void setConfig(INTELLI::ConfigMapPtr cfg); /** * @brief the virtual function provided for outside callers, rewrite in children classes diff --git a/src/CPPAlgos/TugOfWarCPPAlgo.cpp b/src/CPPAlgos/TugOfWarCPPAlgo.cpp index 54e0d592..1306612d 100644 --- a/src/CPPAlgos/TugOfWarCPPAlgo.cpp +++ b/src/CPPAlgos/TugOfWarCPPAlgo.cpp @@ -5,6 +5,10 @@ #include namespace AMMBench { +void TugOfWarCPPAlgo::setConfig(INTELLI::ConfigMapPtr cfg) { + algoDelta = cfg->tryDouble("algoDelta",algoDelta,true); +} + torch::Tensor TugOfWarCPPAlgo::generateTugOfWarMatrix(int64_t m, int64_t n) { double e = 1.0 / std::sqrt(m); torch::Tensor M = torch::randint(2, {m, n}); @@ -15,6 +19,9 @@ torch::Tensor TugOfWarCPPAlgo::amm(torch::Tensor A, torch::Tensor B, uint64_t l2 int64_t n = A.size(1); int64_t p = B.size(1); int64_t l = (int64_t) l2; + + double delta = algoDelta; + int64_t i_iters = static_cast(-std::log(delta)); int64_t j_iters = static_cast(2 * (-std::log(delta) + std::log(-std::log(delta)))); From 6552138427041bc78f66c2f08dfd72d3ce6c5328 Mon Sep 17 00:00:00 2001 From: Lutetium-Vanadium Date: Mon, 12 Jun 2023 12:54:29 +0800 Subject: [PATCH 3/3] Add scripts to scan beta and delta --- benchmark/scripts/scanAlgoBeta/OoOCommon.py | 125 ++++++ benchmark/scripts/scanAlgoBeta/accuBar.py | 328 ++++++++++++++++ benchmark/scripts/scanAlgoBeta/autoParase.py | 87 +++++ .../scripts/scanAlgoBeta/config_CPPBCOOFD.csv | 11 + .../scripts/scanAlgoBeta/config_RAWMM.csv | 9 + .../scripts/scanAlgoBeta/drawTogether.py | 178 +++++++++ benchmark/scripts/scanAlgoBeta/groupBar.py | 236 +++++++++++ benchmark/scripts/scanAlgoBeta/groupBar2.py | 232 +++++++++++ benchmark/scripts/scanAlgoBeta/groupLine.py | 366 ++++++++++++++++++ benchmark/scripts/scanAlgoBeta/perfRu.csv | 7 + benchmark/scripts/scanAlgoDelta/OoOCommon.py | 125 ++++++ benchmark/scripts/scanAlgoDelta/accuBar.py | 328 ++++++++++++++++ benchmark/scripts/scanAlgoDelta/autoParase.py | 87 +++++ .../scripts/scanAlgoDelta/config_CPPTOW.csv | 11 + .../scripts/scanAlgoDelta/config_RAWMM.csv | 9 + .../scripts/scanAlgoDelta/drawTogether.py | 177 +++++++++ benchmark/scripts/scanAlgoDelta/groupBar.py | 236 +++++++++++ benchmark/scripts/scanAlgoDelta/groupBar2.py | 232 +++++++++++ benchmark/scripts/scanAlgoDelta/groupLine.py | 366 ++++++++++++++++++ benchmark/scripts/scanAlgoDelta/perfRu.csv | 7 + figures/algoBeta/algoBeta_cacheMiss.pdf | Bin 0 -> 7700 bytes figures/algoBeta/algoBeta_ebRatio.pdf | Bin 0 -> 7456 bytes figures/algoBeta/algoBeta_elapsedTime.pdf | Bin 0 -> 7725 bytes figures/algoBeta/algoBeta_froError.pdf | Bin 0 -> 7522 bytes figures/algoDelta/algoDelta_cacheMiss.pdf | Bin 0 -> 8432 bytes figures/algoDelta/algoDelta_ebRatio.pdf | Bin 0 -> 8330 bytes figures/algoDelta/algoDelta_elapsedTime.pdf | Bin 0 -> 8710 bytes figures/algoDelta/algoDelta_froError.pdf | Bin 0 -> 8344 bytes 28 files changed, 3157 insertions(+) create mode 100755 benchmark/scripts/scanAlgoBeta/OoOCommon.py create mode 100755 benchmark/scripts/scanAlgoBeta/accuBar.py create mode 100755 benchmark/scripts/scanAlgoBeta/autoParase.py create mode 100644 benchmark/scripts/scanAlgoBeta/config_CPPBCOOFD.csv create mode 100644 benchmark/scripts/scanAlgoBeta/config_RAWMM.csv create mode 100755 benchmark/scripts/scanAlgoBeta/drawTogether.py create mode 100755 benchmark/scripts/scanAlgoBeta/groupBar.py create mode 100755 benchmark/scripts/scanAlgoBeta/groupBar2.py create mode 100755 benchmark/scripts/scanAlgoBeta/groupLine.py create mode 100644 benchmark/scripts/scanAlgoBeta/perfRu.csv create mode 100755 benchmark/scripts/scanAlgoDelta/OoOCommon.py create mode 100755 benchmark/scripts/scanAlgoDelta/accuBar.py create mode 100755 benchmark/scripts/scanAlgoDelta/autoParase.py create mode 100644 benchmark/scripts/scanAlgoDelta/config_CPPTOW.csv create mode 100644 benchmark/scripts/scanAlgoDelta/config_RAWMM.csv create mode 100755 benchmark/scripts/scanAlgoDelta/drawTogether.py create mode 100755 benchmark/scripts/scanAlgoDelta/groupBar.py create mode 100755 benchmark/scripts/scanAlgoDelta/groupBar2.py create mode 100755 benchmark/scripts/scanAlgoDelta/groupLine.py create mode 100644 benchmark/scripts/scanAlgoDelta/perfRu.csv create mode 100644 figures/algoBeta/algoBeta_cacheMiss.pdf create mode 100644 figures/algoBeta/algoBeta_ebRatio.pdf create mode 100644 figures/algoBeta/algoBeta_elapsedTime.pdf create mode 100644 figures/algoBeta/algoBeta_froError.pdf create mode 100644 figures/algoDelta/algoDelta_cacheMiss.pdf create mode 100644 figures/algoDelta/algoDelta_ebRatio.pdf create mode 100644 figures/algoDelta/algoDelta_elapsedTime.pdf create mode 100644 figures/algoDelta/algoDelta_froError.pdf diff --git a/benchmark/scripts/scanAlgoBeta/OoOCommon.py b/benchmark/scripts/scanAlgoBeta/OoOCommon.py new file mode 100755 index 00000000..70f4cf33 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/OoOCommon.py @@ -0,0 +1,125 @@ +import csv +import numpy as np +import matplotlib.pyplot as plt +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator +import os +import pandas as pd +import sys +import matplotlib.ticker as mtick + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 22 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['*', '|', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#FFFFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["////", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + + +def editConfig(src, dest, key, value): + df = pd.read_csv(src, header=None) + rowIdx = 0 + idxt = 0 + for cell in df[0]: + # print(cell) + if (cell == key): + rowIdx = idxt + break + idxt = idxt + 1 + df[1][rowIdx] = str(value) + df.to_csv(dest, index=False, header=False) + + +def readConfig(src, key): + df = pd.read_csv(src, header=None) + rowIdx = 0 + idxt = 0 + for cell in df[0]: + # print(cell) + if (cell == key): + rowIdx = idxt + break + idxt = idxt + 1 + return df[1][rowIdx] + + +def draw2yLine(NAME, Com, R1, R2, l1, l2, m1, m2, fname): + fig, ax1 = plt.subplots(figsize=(10, 6.4)) + lines = [None] * 2 + # ax1.set_ylim(0, 1) + print(Com) + print(R1) + lines[0], = ax1.plot(Com, R1, color=LINE_COLORS[0], \ + linewidth=LINE_WIDTH, marker=MARKERS[0], \ + markersize=MARKER_SIZE + # + ) + + # plt.show() + ax1.set_ylabel(m1, fontproperties=LABEL_FP) + ax1.set_xlabel(NAME, fontproperties=LABEL_FP) + # ax1.set_xticklabels(ax1.get_xticklabels()) # 设置共用的x轴 + plt.xticks(rotation=0, size=TICK_FONT_SIZE) + plt.yticks(rotation=0, size=TICK_FONT_SIZE) + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + ax2 = ax1.twinx() + + # ax2.set_ylabel('latency/us') + # ax2.set_ylim(0, 0.5) + lines[1], = ax2.plot(Com, R2, color=LINE_COLORS[1], \ + linewidth=LINE_WIDTH, marker=MARKERS[1], \ + markersize=MARKER_SIZE) + + ax2.set_ylabel(m2, fontproperties=LABEL_FP) + # ax2.vlines(192000, min(R2)-1, max(R2)+1, colors = "GREEN", linestyles = "dashed",label='total L1 size') + # plt.grid(axis='y', color='gray') + + # style = dict(size=10, color='black') + # ax2.hlines(tset, 0, x2_list[len(x2_list)-1]+width, colors = "r", linestyles = "dashed",label="tset") + # ax2.text(4, tset, "$T_{set}$="+str(tset)+"us", ha='right', **style) + + # plt.xlabel('batch', fontproperties=LABEL_FP) + + # plt.xscale('log') + # figure.xaxis.set_major_locator(LinearLocator(5)) + ax1.yaxis.set_major_locator(LinearLocator(5)) + ax2.yaxis.set_major_locator(LinearLocator(5)) + ax1.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax2.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax1.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax2.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + plt.legend(lines, + [l1, l2], + prop=LEGEND_FP, + loc='upper center', + ncol=1, + bbox_to_anchor=(0.55, 1.3 + ), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=-1.5, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + plt.yticks(rotation=0, size=TICK_FONT_SIZE) + plt.tight_layout() + + plt.savefig(fname + ".pdf") diff --git a/benchmark/scripts/scanAlgoBeta/accuBar.py b/benchmark/scripts/scanAlgoBeta/accuBar.py new file mode 100755 index 00000000..638c8a60 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/accuBar.py @@ -0,0 +1,328 @@ +import getopt +import os +import sys + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LinearLocator, LogLocator, MaxNLocator, ScalarFormatter +from numpy import double + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 26 +TITLE_FRONT_SIZE = 32 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) +TITLE_FP = FontProperties(style='normal', size=TITLE_FRONT_SIZE) +MARKERS = (['o', 's', 'v', "^", "h", "v", ">", "x", "d", "<", "|", "", "|", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ('#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["\\", "///", "o", "||", "\\\\", "\\\\", "//////", "//////", ".", "\\\\\\", "\\\\\\"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 0.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +# there are some embedding problems if directly exporting the pdf figure using matplotlib. +# so we generate the eps format first and convert it to pdf. +def ConvertEpsToPdf(dir_filename): + os.system("epstopdf --outfile " + dir_filename + ".pdf " + dir_filename + ".eps") + os.system("rm -rf " + dir_filename + ".eps") + + +class ScalarFormatterForceFormat(ScalarFormatter): + def _set_format(self): # Override function that finds format to use. + self.format = "%1.1f" # Give format here + + +# draw a line chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, filename, allow_legend, title): + # you may change the figure size on your own. + + fig = plt.figure(figsize=(16, 9)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # if not os.path.exists(FIGURE_FOLDER): + # os.makedirs(FIGURE_FOLDER) + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.5 + # draw the bars + bottom_base = np.zeros(len(y_values[0])) + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + width / 2, y_values[i], width, hatch=PATTERNS[i], color=LINE_COLORS[i], + label=FIGURE_LABEL[i], bottom=bottom_base, edgecolor='black', linewidth=3) + bottom_base = np.array(y_values[i]) + bottom_base + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL + # mode='expand', + # shadow=False, + # columnspacing=0.25, + # labelspacing=-2.2, + # borderpad=5, + # bbox_transform=ax.transAxes, + # frameon=False, + # columnspacing=5.5, + # handlelength=2, + ) + if allow_legend == True: + handles, labels = figure.get_legend_handles_labels() + if allow_legend == True: + leg = plt.legend(handles[::-1], labels[::-1], + loc='upper center', + # prop=#LEGEND_FP, + # ncol=3, + # bbox_to_anchor=(0.5, 1.25), + # bbox_to_anchor=(1.17, 0.5), + # handletextpad=0.1, + # borderaxespad=0.0, + # handlelength=1.8, + # labelspacing=0.3, + # columnspacing=0.3, + ) + leg.get_frame().set_linewidth(2) + leg.get_frame().set_edgecolor("black") + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 0.6 * width, x_values) + yfmt = ScalarFormatterForceFormat() + yfmt.set_powerlimits((0, 0)) + figure.get_yaxis().set_major_formatter(yfmt) + plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0), useMathText=True) + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(3)) + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.yaxis.set_major_locator(LinearLocator(6)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + plt.title(title, fontproperties=TITLE_FP) + plt.savefig(filename + ".pdf", bbox_inches='tight', format='pdf') + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, hatch=PATTERNS[i], color=LINE_COLORS[i], + linewidth=0.2) + + # LEGEND + figlegend = pylab.figure(figsize=(11, 0.5)) + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=9, + bbox_to_anchor=(0, 0.4, 1, 1), + ncol=len(FIGURE_LABEL), mode="expand", shadow=False, \ + frameon=False, handlelength=1.1, handletextpad=0.2, columnspacing=0.1) + + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +def normalize(y_values): + y_total_values = np.zeros(len(y_values[0])) + + for i in range(len(y_values)): + y_total_values += np.array(y_values[i]) + y_norm_values = [] + + for i in range(len(y_values)): + y_norm_values.append(np.array(y_values[i]) / (y_total_values) * 100) + return y_norm_values + + +# example for reading csv file +def ReadFile(id): + # Creates a list containing w lists, each of h items, all set to 0 + w, h = 5, 3 + y = [[0 for x in range(w)] for y in range(h)] + # print(matches) + max_value = 0 + j = 0 + bound = id + 1 * w + for i in range(id, bound, 1): + cnt = 0 + print(i) + f = open(exp_dir + "/results/breakdown/PMJ_JBCR_NP_{}.txt".format(i), "r") + read = f.readlines() + others = 0 + for x in read: + value = double(x.strip("\n")) + if value > max_value: + max_value = value + elif cnt == 3: # sort + y[0][j] = value + elif cnt == 4: # merge + y[1][j] = value + elif cnt == 5: # join + y[2][j] = value + else: + others += value + # if cnt == 6: + # y[2][j] = others + cnt += 1 + j += 1 + print(y) + return y, max_value + + +if __name__ == "__main__": + id = 119 + try: + opts, args = getopt.getopt(sys.argv[1:], '-i:h', ['test id', 'help']) + except getopt.GetoptError: + print('breakdown.py -id testid') + sys.exit(2) + for opt, opt_value in opts: + if opt in ('-h', '--help'): + print("[*] Help info") + exit() + elif opt == '-i': + print('Test ID:', opt_value) + id = (int)(opt_value) + + x_values = ['10%', '20%', '30%', '40%', '50%'] # sorting step size + + y_values, max_value = ReadFile(id) # 55 + + # y_norm_values = normalize(y_values) + + # break into 4 parts + legend_labels = ['sort', 'merge', 'join'] # , 'others' + + DrawFigure(x_values, y_values, legend_labels, + 'sorting step size', 'cycles per input tuple', + 'breakdown_sort_figure', True) + + # DrawLegend(legend_labels, 'breakdown_radix_legend') + + +def DrawPercentageFigure(x_values, y_values, legend_labels, x_label, y_label, filename, allow_legend, title): + # you may change the figure size on your own. + fig = plt.figure(figsize=(9, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.5 + # draw the bars + bottom_base = np.zeros(len(y_values[0])) + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + width / 2, y_values[i], width, hatch=PATTERNS[i], color=LINE_COLORS[i], + label=FIGURE_LABEL[i], bottom=bottom_base, edgecolor='black', linewidth=3) + bottom_base = np.array(y_values[i]) + bottom_base + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL + # mode='expand', + # shadow=False, + # columnspacing=0.25, + # labelspacing=-2.2, + # borderpad=5, + # bbox_transform=ax.transAxes, + # frameon=False, + # columnspacing=5.5, + # handlelength=2, + ) + if allow_legend == True: + handles, labels = figure.get_legend_handles_labels() + if allow_legend == True: + print(handles[::-1], labels[::-1]) + leg = plt.legend(handles[::-1], labels[::-1], + loc='center', + prop=LEGEND_FP, + ncol=3, + bbox_to_anchor=(0.5, 1.2), + handletextpad=0.1, + borderaxespad=0.0, + handlelength=1.8, + labelspacing=0.3, + columnspacing=0.3, + ) + leg.get_frame().set_linewidth(2) + leg.get_frame().set_edgecolor("black") + + # sometimes you may not want to draw legends. + # if allow_legend == True: + # leg=plt.legend(bars, + # FIGURE_LABEL, + # prop=LEGEND_FP, + # loc='right', + # ncol=1, + # # mode='expand', + # bbox_to_anchor=(0.45, 1.1), shadow=False, + # columnspacing=0.1, + # frameon=True, borderaxespad=0.0, handlelength=1.5, + # handletextpad=0.1, + # labelspacing=0.1) + # leg.get_frame().set_linewidth(2) + # leg.get_frame().set_edgecolor("black") + + plt.ylim(0, 100) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 0.5 * width, x_values) + plt.xticks(rotation=30) + + # plt.xlim(0,) + # plt.ylim(0,1) + + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(6)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + plt.savefig(filename + ".pdf", bbox_inches='tight', format='pdf') diff --git a/benchmark/scripts/scanAlgoBeta/autoParase.py b/benchmark/scripts/scanAlgoBeta/autoParase.py new file mode 100755 index 00000000..9375c8e0 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/autoParase.py @@ -0,0 +1,87 @@ +import csv + + +def paraseValidStageNames(a): + nameList = [] + with open(a, 'r') as f: + reader = csv.reader(f) + # reader = [each for each in csv.DictReader(f, delimiter=',')] + result = list(reader) + rows = len(result) + # print('rows=',rows) + firstRow = result[0] + # print(firstRow) + index = 0 + # define what may attract our interest + idxCpu = 0 + idxName = 0 + for i in firstRow: + # print(i) + if (i == 'cpu'): + idxCpu = index + if (i == 'name'): + idxName = index + index = index + 1 + # read the valid stages + vdataEntries = 0 + + for k in range(1, rows): + if (result[k][idxCpu] != 'NA'): + R1 = ((result[k][idxName])) + nameList.append(R1) + return nameList + + +def paraseValidColums(a, nameList, colTitle): + with open(a, 'r') as f: + reader = csv.reader(f) + # reader = [each for each in csv.DictReader(f, delimiter=',')] + result = list(reader) + rows = len(result) + # print('rows=',rows) + firstRow = result[0] + # print(firstRow) + index = 0 + # define what may attract our interest + idxCpu = 0 + idxName = 0 + idxTitle = 0 + for i in firstRow: + # print(i) + if (i == 'cpu'): + idxCpu = index + if (i == 'name'): + idxName = index + if (i == colTitle): + idxTitle = index + index = index + 1 + # read the valid stages + vdataEntries = 0 + ru = [] + for k in range(1, rows): + if (result[k][idxCpu] != 'NA'): + R1 = ((result[k][idxName])) + for j in range(len(nameList)): + if (R1 == nameList[j]): + s = int(result[k][idxTitle]) + ru.append(s) + break + return ru + + +def maxInList(a): + # a in [[1,2] [3,4]] + inLen = len(a[0]) + ru = [] + index = [] + ti = 0 + for i in range(len(a[0])): + ts = 0 + ti = 0 + for k in range(len(a)): + if (a[k][i] > ts): + ts = a[k][i] + ti = k + ru.append(ts) + index.append(ti) + return ru, index diff --git a/benchmark/scripts/scanAlgoBeta/config_CPPBCOOFD.csv b/benchmark/scripts/scanAlgoBeta/config_CPPBCOOFD.csv new file mode 100644 index 00000000..3db65119 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/config_CPPBCOOFD.csv @@ -0,0 +1,11 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/BetaCoOccurringFD.pt,String +useCPP,1,U64 +cppAlgoTag,bcooFD,String +threads,1,U64 +forceMP,1,U64 +algoBeta,1.0,Double diff --git a/benchmark/scripts/scanAlgoBeta/config_RAWMM.csv b/benchmark/scripts/scanAlgoBeta/config_RAWMM.csv new file mode 100644 index 00000000..db4593f3 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/config_RAWMM.csv @@ -0,0 +1,9 @@ +key,value,type +aRow,1000,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/RAWMM.pt,String +threads,1,U64 +forceMP,1,U64 +algoBeta,1.0,Double diff --git a/benchmark/scripts/scanAlgoBeta/drawTogether.py b/benchmark/scripts/scanAlgoBeta/drawTogether.py new file mode 100755 index 00000000..203b84f4 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/drawTogether.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python3 +import csv +import numpy as np +import accuBar as accuBar +import groupBar as groupBar +import groupBar2 as groupBar2 +import groupLine as groupLine +from autoParase import * +import itertools as it +import os + +import matplotlib +import numpy as np +import pylab +import matplotlib.font_manager as fm +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator +import os +import pandas as pd +import sys +from OoOCommon import * +import time + +# OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 22 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['*', '|', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#FFFFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["////", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +scanTag = "algoBeta" + + +def singleRun(exePath, singleValue, resultPath, configTemplate): + # resultFolder="singleValueTests" + configFname = "config_" + scanTag + str(singleValue) + ".csv" + # configTemplate = "config.csv" + # clear old files + os.system("cd " + exePath + "&& sudo rm *.csv") + + # editConfig(configTemplate, exePath + configFname, "earlierEmitMs", 0) + editConfig(configTemplate, exePath + configFname, scanTag, singleValue) + # prepare new file + # run + os.system("cd " + exePath + "&& sudo ./benchmark " + configFname) + # copy result + os.system("sudo rm -rf " + resultPath + "/" + str(singleValue)) + os.system("sudo mkdir " + resultPath + "/" + str(singleValue)) + os.system("cd " + exePath + "&& sudo cp *.csv " + resultPath + "/" + str(singleValue)) + + +def runScanVector(exePath, singleValueVec, resultPath, templateName="config.csv"): + for i in singleValueVec: + singleRun(exePath, i, resultPath, templateName) + + +def readResultSingle(singleValue, resultPath): + resultFname = resultPath + "/" + str(singleValue) + "/default.csv" + elapsedTime = readConfig(resultFname, "perfElapsedTime") + cacheMiss = readConfig(resultFname, "cacheMiss") + cacheRefs = readConfig(resultFname, "cacheRefs") + froError = readConfig(resultFname, "froError") + errorBoundRatio = readConfig(resultFname, "errorBoundRatio") + return elapsedTime, cacheMiss, cacheRefs, froError, errorBoundRatio + + +def cleanPath(path): + os.system("sudo rm -rf " + path) + os.system("sudo mkdir " + path) + + +def readResultVector(singleValueVec, resultPath): + elapseTimeVec = [] + cacheMissVec = [] + cacheRefVec = [] + froErrorVec = [] + errorBoundRatioVec = [] + for i in singleValueVec: + elapsedTime, cacheMiss, cacheRefs, froError, errorBoundRatio = readResultSingle(i, resultPath) + elapseTimeVec.append(float(elapsedTime) / 1000.0) + cacheMissVec.append(float(cacheMiss)) + cacheRefVec.append(float(cacheRefs)) + froErrorVec.append(float(froError)) + errorBoundRatioVec.append(float(errorBoundRatio)) + return np.array(elapseTimeVec), np.array(cacheMissVec), np.array(cacheRefVec), np.array(froErrorVec), np.array( + errorBoundRatioVec) + + +def compareMethod(exeSpace, commonPathBase, resultPaths, csvTemplates, periodVec, reRun=1): + elapsedTimeAll = [] + cacheMissAll = [] + cacheRefAll = [] + periodAll = [] + froAll = [] + errorBoundRatioAll = [] + for i in range(len(csvTemplates)): + resultPath = commonPathBase + resultPaths[i] + if (reRun == 1): + os.system("sudo rm -rf " + resultPath) + os.system("sudo mkdir " + resultPath) + runScanVector(exeSpace, periodVec, resultPath, csvTemplates[i]) + elapsedTime, cacheMiss, cacheRef, fro, eb = readResultVector(periodVec, resultPath) + elapsedTimeAll.append(elapsedTime) + cacheMissAll.append(cacheMiss) + cacheRefAll.append(cacheRef) + periodAll.append(periodVec) + cacheMissRateAll = np.array(cacheMissAll) / np.array(cacheRefAll) * 100.0 + froAll.append(fro) + errorBoundRatioAll.append(eb) + # periodAll.append(periodVec) + return np.array(elapsedTimeAll), cacheMissRateAll, periodAll, np.array(froAll), np.array(errorBoundRatioAll) + + +def main(): + exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" + commonBase = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/" + figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag + methodTags = ["BCo-AMM", "MM"] + resultPaths = ["co", "mm"] + csvTemplates = ["config_CPPBCOOFD.csv", "config_RAWMM.csv"] + valueVec = [1.0, 5.0, 10.0, 15.0, 20.0, 30.0, 40.0, 50.0, 60.0, 70.0, 80.0, 88.0] + valueVecDisp = np.array(valueVec) + # run + reRun = 0 + if (len(sys.argv) < 2): + os.system("mkdir ../../results") + os.system("mkdir ../../figures") + os.system("mkdir " + figPath) + os.system("sudo rm -rf " + commonBase) + os.system("sudo mkdir " + commonBase) + reRun = 1 + + elapsedTimeAll, cacheMissAll, periodAll,fro,eb = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, + reRun) + groupLine.DrawFigure(periodAll, elapsedTimeAll, + methodTags, + "value of beta", "elapsed time (ms)", 0, 1, + figPath + "/" + scanTag + "_elapsedTime", + True) + groupLine.DrawFigureYnormal(periodAll, cacheMissAll, + methodTags, + "value of beta", "cacheMiss (%)", 0, 1, + figPath + "/" + scanTag + "_cacheMiss", + True) + groupLine.DrawFigureYnormal(periodAll, + fro * 100.0, + methodTags, + "value of beta", "normalized error %", 0, 1, figPath + "/" +scanTag + "_froError", + True) + groupLine.DrawFigureYnormal(periodAll, + eb * 100.0, + methodTags, + "value of beta", "error bound ratio %", 0, 1, figPath + "/" + scanTag + "_ebRatio", + True) + + +if __name__ == "__main__": + main() diff --git a/benchmark/scripts/scanAlgoBeta/groupBar.py b/benchmark/scripts/scanAlgoBeta/groupBar.py new file mode 100755 index 00000000..ef2d9842 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/groupBar.py @@ -0,0 +1,236 @@ +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 15 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (["", 'o', 's', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#7FFFFF', '#B03A2E', '#2874A6', '#FFFFFF', '#7FFFFF', '#B03A2E', '#2874A6', '#FFFFFF', '#F5CBA7', '#82E0AA', + '#AEB6BF', + '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = ( + ["////", "\\\\", "//", "o", "*", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + figlegend = pylab.figure(figsize=(16, 0.5)) + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], + edgecolor='black', linewidth=3) + + # LEGEND + + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=True, \ + frameon=True, handlelength=2, handletextpad=0.3, columnspacing=0.5, + borderaxespad=-0.2, fancybox=True + ) + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +# draw a bar chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.08 + # draw the bars + bars = [] + ts = 0 + pos = 0 + gl = len(y_values[0]) + for i in range(len(y_values)): + pos = pos + 3 * width + for j in range(len(y_values[i])): + pos = pos + width + bar = plt.bar(pos, y_values[i][j], width, hatch=PATTERNS[j], color=LINE_COLORS[j], label=FIGURE_LABEL[j], + edgecolor='black', linewidth=3) + bars.append(bar) + ts = ts + 1 + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL, + prop=LEGEND_FP, + ncol=4, + loc='upper center', + # mode='expand', + shadow=False, + bbox_to_anchor=(0.45, 1.6), + columnspacing=0.1, + handletextpad=0.2, + # bbox_transform=ax.transAxes, + # frameon=True, + # columnspacing=5.5, + # handlelength=2, + ) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index, x_values) + # plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + # plt.grid(axis='y', color='gray') + # figure.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) + + # you may need to tune the xticks position to get the best figure. + # plt.yscale('log') + # + # plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(5)) + # figure.xaxis.set_major_locator(LinearLocator(5)) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + plt.ylim(y_min, y_max) + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + col9 = [] + + for id in it.chain(range(38, 42)): + col9.append(0) + y.append(col9) # this is a lz4_pipe2 empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col1.append(x) + y.append(col1) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col2.append(x) + y.append(col2) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col3.append(x) + y.append(col3) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col4.append(x) + y.append(col4) + + y.append(col9) # this is a lz4_pipe2 empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col5.append(x) + y.append(col5) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col6.append(x) + y.append(col6) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col7.append(x) + y.append(col7) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col8.append(x) + y.append(col8) + return y + + +if __name__ == "__main__": + x_values = ["Stock", "Rovio", "YSB", "DEBS"] + + y_values = ReadFile() + + legend_labels = ['Lazy:', 'NPJ', 'PRJ', 'MWAY', 'MPASS', + 'Eager:', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', 'PMJ$^{JB}$'] + print(y_values) + DrawFigure(x_values, y_values, legend_labels, + '', 'Latency (ms)', 0, + 400, 'latency_figure_app', False) + + # DrawLegend(legend_labels, 'latency_legend') diff --git a/benchmark/scripts/scanAlgoBeta/groupBar2.py b/benchmark/scripts/scanAlgoBeta/groupBar2.py new file mode 100755 index 00000000..31155695 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/groupBar2.py @@ -0,0 +1,232 @@ +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (["", 'o', 's', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#FFFFFF', '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#00FFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', + '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = ( + ["", "////", "\\\\", "//", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", + "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + figlegend = pylab.figure(figsize=(16, 0.5)) + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], + edgecolor='black', linewidth=3) + + # LEGEND + + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=True, \ + frameon=True, handlelength=2, handletextpad=0.3, columnspacing=0.5, + borderaxespad=-0.2, fancybox=True + ) + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +# draw a bar chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.12 + # draw the bars + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + i * width + width / 2, + y_values[i], width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], edgecolor='black', linewidth=3) + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL, + prop=LEGEND_FP, + ncol=3, + loc='upper center', + # mode='expand', + shadow=False, + bbox_to_anchor=(0.45, 1.7), + columnspacing=0.1, + handletextpad=0.2, + # bbox_transform=ax.transAxes, + # frameon=True, + # columnspacing=5.5, + # handlelength=2, + ) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 3 * width, x_values, rotation=30) + + # plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + # plt.grid(axis='y', color='gray') + # figure.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) + + # you may need to tune the xticks position to get the best figure. + # plt.yscale('log') + # + # plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(10)) + # figure.xaxis.set_major_locator(LinearLocator(5)) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + col9 = [] + + for id in it.chain(range(38, 42)): + col9.append(0) + y.append(col9) # this is a fake empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col1.append(x) + y.append(col1) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col2.append(x) + y.append(col2) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col3.append(x) + y.append(col3) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col4.append(x) + y.append(col4) + + y.append(col9) # this is a fake empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col5.append(x) + y.append(col5) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col6.append(x) + y.append(col6) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col7.append(x) + y.append(col7) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col8.append(x) + y.append(col8) + return y + + +if __name__ == "__main__": + x_values = ["Stock", "Rovio", "YSB", "DEBS"] + + y_values = ReadFile() + + legend_labels = ['Lazy:', 'NPJ', 'PRJ', 'MWAY', 'MPASS', + 'Eager:', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', 'PMJ$^{JB}$'] + print(y_values) + DrawFigure(x_values, y_values, legend_labels, + '', 'Latency (ms)', 0, + 400, 'latency_figure_app', False) + + # DrawLegend(legend_labels, 'latency_legend') diff --git a/benchmark/scripts/scanAlgoBeta/groupLine.py b/benchmark/scripts/scanAlgoBeta/groupLine.py new file mode 100755 index 00000000..8110fd3b --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/groupLine.py @@ -0,0 +1,366 @@ +import itertools as it +import os +import matplotlib.pyplot as plt +import matplotlib.font_manager as fm +import matplotlib +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import MaxNLocator +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LinearLocator, LogLocator, MaxNLocator, ScalarFormatter +from numpy import double + +# 获取系统中可用的字体路径 +# font_paths = fm.findSystemFonts() +# OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 20 +LABEL_FONT_SIZE = 20 +LEGEND_FONT_SIZE = 20 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['o', 's', 'v', "^", "h", "v", ">", "x", "d", "<", "|", "p", "+", "_", "%", "|", "|", "|", "|", "|"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#F15854', '#5DA5DA', '#60BD68', '#B276B2', '#DECF3F', '#F17CB0', '#B2912F', '#FAA43A', '#AFAFAF', '#087878', + '#783456', + '#560012', '#431256', "#00AABB", "#AA00BB") +# you may want to change the patterns for different figures +PATTERNS = (["|", "\\", "/", "+", "-", ".", "*", "x", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 13.0 +MARKER_FREQUENCY = 1000 + +# matplotlib.rcParams['ps.useafm'] = True +# matplotlib.rcParams['pdf.use14corefonts'] = True +# matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +# matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +# 创建字体列表 +# Explicitly specify the font path +# 获取系统中可用的字体路径 +font_paths = fm.findSystemFonts() + +# 创建字体列表 +font_list = [] +for font_path in font_paths: + try: + font_name = fm.FontProperties(fname=font_path).get_name() + if font_name not in font_list: + font_list.append(font_name) + except: + pass + +# 配置 matplotlib 使用系统中可用的字体 +plt.rcParams['font.family'] = font_list[0] + +FIGURE_FOLDER = '/data1/xtra/results/figure' + + +# there are some embedding problems if directly exporting the pdf figure using matplotlib. +# so we generate the eps format first and convert it to pdf. +def ConvertEpsToPdf(dir_filename): + os.system("epstopdf --outfile " + dir_filename + ".pdf " + dir_filename + ".eps") + os.system("rm -rf " + dir_filename + ".eps") + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LINE_WIDTH = 8.0 + MARKER_SIZE = 12.0 + LEGEND_FP = FontProperties(style='normal', size=26) + + figlegend = pylab.figure(figsize=(12, 0.5)) + idx = 0 + lines = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + idx = 0 + for group in range(len(FIGURE_LABEL)): + lines[idx], = ax1.plot(x_values, data, + color=LINE_COLORS[idx], linewidth=LINE_WIDTH, + marker=MARKERS[idx], markersize=MARKER_SIZE, label=str(group)) + idx = idx + 1 + + # LEGEND + figlegend.legend(lines, FIGURE_LABEL, prop=LEGEND_FP, + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=False, + frameon=False, borderaxespad=0.0, handlelength=2) + + if not os.path.exists(FIGURE_FOLDER): + os.makedirs(FIGURE_FOLDER) + # no need to export eps in this case. + figlegend.savefig(filename + '.pdf') + + +# draw a line chart +def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i]) + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + # mode='expand', + bbox_to_anchor=(0.55, 1.6), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0.0, handlelength=1.5, + handletextpad=0.1, + labelspacing=0.1) + plt.xscale('log') + plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LogLocator(base=10)) + figure.xaxis.set_major_locator(LogLocator(base=10)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# draw a line chart +def DrawFigureXYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i], markeredgecolor='k') + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + bbox_to_anchor=(0.55, 1.5), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + # plt.xscale('log') + # plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.xaxis.set_major_locator(LogLocator(base=10)) + plt.xticks(rotation=0, fontsize=TICK_FONT_SIZE) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# draw a line chart +def DrawFigureYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i], markeredgecolor='k') + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + bbox_to_anchor=(0.55, 1.5), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + plt.xscale('log') + # plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.xaxis.set_major_locator(LogLocator(base=10)) + plt.xticks(rotation=0, fontsize=TICK_FONT_SIZE) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col1.append(value) + y.append(col1) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col2.append(value) + y.append(col2) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col3.append(value) + y.append(col3) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col4.append(value) + y.append(col4) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col5.append(value) + y.append(col5) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col6.append(value) + y.append(col6) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col7.append(value) + y.append(col7) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col8.append(value) + y.append(col8) + return y + + +if __name__ == "__main__": + # x_values = ['Unique', 'Zipf(0)', 'Zipf(0.2)', 'Zipf(0.4)', 'Zipf(0.8)', 'Zipf(1)'] + x_values = [1600, 3200, 6400, 12800, 25600] + + y_values = ReadFile() + + legend_labels = ['NPJ', 'PRJ', 'MWAY', 'MPASS', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', + 'PMJ$^{JB}$'] + + DrawFigure(x_values, y_values, legend_labels, + 'Input arrival rate of R (e/ms)', 'Tpt. (#matches/ms)', x_values[0], + x_values[4], 'throughput_figure1_1', False) + +# DrawLegend(legend_labels, 'factor_legend') diff --git a/benchmark/scripts/scanAlgoBeta/perfRu.csv b/benchmark/scripts/scanAlgoBeta/perfRu.csv new file mode 100644 index 00000000..9ee43623 --- /dev/null +++ b/benchmark/scripts/scanAlgoBeta/perfRu.csv @@ -0,0 +1,7 @@ +key,value,type +cacheMiss,12491377,U64 +cacheRefs,35327177,U64 +cpuClock,2478812100,U64 +cpuCycle,9889422467,U64 +instructions,16997458033,U64 +taskClock,2478813000,U64 diff --git a/benchmark/scripts/scanAlgoDelta/OoOCommon.py b/benchmark/scripts/scanAlgoDelta/OoOCommon.py new file mode 100755 index 00000000..70f4cf33 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/OoOCommon.py @@ -0,0 +1,125 @@ +import csv +import numpy as np +import matplotlib.pyplot as plt +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator +import os +import pandas as pd +import sys +import matplotlib.ticker as mtick + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 22 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['*', '|', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#FFFFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["////", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + + +def editConfig(src, dest, key, value): + df = pd.read_csv(src, header=None) + rowIdx = 0 + idxt = 0 + for cell in df[0]: + # print(cell) + if (cell == key): + rowIdx = idxt + break + idxt = idxt + 1 + df[1][rowIdx] = str(value) + df.to_csv(dest, index=False, header=False) + + +def readConfig(src, key): + df = pd.read_csv(src, header=None) + rowIdx = 0 + idxt = 0 + for cell in df[0]: + # print(cell) + if (cell == key): + rowIdx = idxt + break + idxt = idxt + 1 + return df[1][rowIdx] + + +def draw2yLine(NAME, Com, R1, R2, l1, l2, m1, m2, fname): + fig, ax1 = plt.subplots(figsize=(10, 6.4)) + lines = [None] * 2 + # ax1.set_ylim(0, 1) + print(Com) + print(R1) + lines[0], = ax1.plot(Com, R1, color=LINE_COLORS[0], \ + linewidth=LINE_WIDTH, marker=MARKERS[0], \ + markersize=MARKER_SIZE + # + ) + + # plt.show() + ax1.set_ylabel(m1, fontproperties=LABEL_FP) + ax1.set_xlabel(NAME, fontproperties=LABEL_FP) + # ax1.set_xticklabels(ax1.get_xticklabels()) # 设置共用的x轴 + plt.xticks(rotation=0, size=TICK_FONT_SIZE) + plt.yticks(rotation=0, size=TICK_FONT_SIZE) + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + ax2 = ax1.twinx() + + # ax2.set_ylabel('latency/us') + # ax2.set_ylim(0, 0.5) + lines[1], = ax2.plot(Com, R2, color=LINE_COLORS[1], \ + linewidth=LINE_WIDTH, marker=MARKERS[1], \ + markersize=MARKER_SIZE) + + ax2.set_ylabel(m2, fontproperties=LABEL_FP) + # ax2.vlines(192000, min(R2)-1, max(R2)+1, colors = "GREEN", linestyles = "dashed",label='total L1 size') + # plt.grid(axis='y', color='gray') + + # style = dict(size=10, color='black') + # ax2.hlines(tset, 0, x2_list[len(x2_list)-1]+width, colors = "r", linestyles = "dashed",label="tset") + # ax2.text(4, tset, "$T_{set}$="+str(tset)+"us", ha='right', **style) + + # plt.xlabel('batch', fontproperties=LABEL_FP) + + # plt.xscale('log') + # figure.xaxis.set_major_locator(LinearLocator(5)) + ax1.yaxis.set_major_locator(LinearLocator(5)) + ax2.yaxis.set_major_locator(LinearLocator(5)) + ax1.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax2.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax1.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + ax2.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.1f')) + plt.legend(lines, + [l1, l2], + prop=LEGEND_FP, + loc='upper center', + ncol=1, + bbox_to_anchor=(0.55, 1.3 + ), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=-1.5, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + plt.yticks(rotation=0, size=TICK_FONT_SIZE) + plt.tight_layout() + + plt.savefig(fname + ".pdf") diff --git a/benchmark/scripts/scanAlgoDelta/accuBar.py b/benchmark/scripts/scanAlgoDelta/accuBar.py new file mode 100755 index 00000000..638c8a60 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/accuBar.py @@ -0,0 +1,328 @@ +import getopt +import os +import sys + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LinearLocator, LogLocator, MaxNLocator, ScalarFormatter +from numpy import double + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 26 +TITLE_FRONT_SIZE = 32 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) +TITLE_FP = FontProperties(style='normal', size=TITLE_FRONT_SIZE) +MARKERS = (['o', 's', 'v', "^", "h", "v", ">", "x", "d", "<", "|", "", "|", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ('#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["\\", "///", "o", "||", "\\\\", "\\\\", "//////", "//////", ".", "\\\\\\", "\\\\\\"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 0.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +# there are some embedding problems if directly exporting the pdf figure using matplotlib. +# so we generate the eps format first and convert it to pdf. +def ConvertEpsToPdf(dir_filename): + os.system("epstopdf --outfile " + dir_filename + ".pdf " + dir_filename + ".eps") + os.system("rm -rf " + dir_filename + ".eps") + + +class ScalarFormatterForceFormat(ScalarFormatter): + def _set_format(self): # Override function that finds format to use. + self.format = "%1.1f" # Give format here + + +# draw a line chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, filename, allow_legend, title): + # you may change the figure size on your own. + + fig = plt.figure(figsize=(16, 9)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # if not os.path.exists(FIGURE_FOLDER): + # os.makedirs(FIGURE_FOLDER) + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.5 + # draw the bars + bottom_base = np.zeros(len(y_values[0])) + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + width / 2, y_values[i], width, hatch=PATTERNS[i], color=LINE_COLORS[i], + label=FIGURE_LABEL[i], bottom=bottom_base, edgecolor='black', linewidth=3) + bottom_base = np.array(y_values[i]) + bottom_base + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL + # mode='expand', + # shadow=False, + # columnspacing=0.25, + # labelspacing=-2.2, + # borderpad=5, + # bbox_transform=ax.transAxes, + # frameon=False, + # columnspacing=5.5, + # handlelength=2, + ) + if allow_legend == True: + handles, labels = figure.get_legend_handles_labels() + if allow_legend == True: + leg = plt.legend(handles[::-1], labels[::-1], + loc='upper center', + # prop=#LEGEND_FP, + # ncol=3, + # bbox_to_anchor=(0.5, 1.25), + # bbox_to_anchor=(1.17, 0.5), + # handletextpad=0.1, + # borderaxespad=0.0, + # handlelength=1.8, + # labelspacing=0.3, + # columnspacing=0.3, + ) + leg.get_frame().set_linewidth(2) + leg.get_frame().set_edgecolor("black") + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 0.6 * width, x_values) + yfmt = ScalarFormatterForceFormat() + yfmt.set_powerlimits((0, 0)) + figure.get_yaxis().set_major_formatter(yfmt) + plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0), useMathText=True) + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(3)) + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.yaxis.set_major_locator(LinearLocator(6)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + plt.title(title, fontproperties=TITLE_FP) + plt.savefig(filename + ".pdf", bbox_inches='tight', format='pdf') + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, hatch=PATTERNS[i], color=LINE_COLORS[i], + linewidth=0.2) + + # LEGEND + figlegend = pylab.figure(figsize=(11, 0.5)) + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=9, + bbox_to_anchor=(0, 0.4, 1, 1), + ncol=len(FIGURE_LABEL), mode="expand", shadow=False, \ + frameon=False, handlelength=1.1, handletextpad=0.2, columnspacing=0.1) + + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +def normalize(y_values): + y_total_values = np.zeros(len(y_values[0])) + + for i in range(len(y_values)): + y_total_values += np.array(y_values[i]) + y_norm_values = [] + + for i in range(len(y_values)): + y_norm_values.append(np.array(y_values[i]) / (y_total_values) * 100) + return y_norm_values + + +# example for reading csv file +def ReadFile(id): + # Creates a list containing w lists, each of h items, all set to 0 + w, h = 5, 3 + y = [[0 for x in range(w)] for y in range(h)] + # print(matches) + max_value = 0 + j = 0 + bound = id + 1 * w + for i in range(id, bound, 1): + cnt = 0 + print(i) + f = open(exp_dir + "/results/breakdown/PMJ_JBCR_NP_{}.txt".format(i), "r") + read = f.readlines() + others = 0 + for x in read: + value = double(x.strip("\n")) + if value > max_value: + max_value = value + elif cnt == 3: # sort + y[0][j] = value + elif cnt == 4: # merge + y[1][j] = value + elif cnt == 5: # join + y[2][j] = value + else: + others += value + # if cnt == 6: + # y[2][j] = others + cnt += 1 + j += 1 + print(y) + return y, max_value + + +if __name__ == "__main__": + id = 119 + try: + opts, args = getopt.getopt(sys.argv[1:], '-i:h', ['test id', 'help']) + except getopt.GetoptError: + print('breakdown.py -id testid') + sys.exit(2) + for opt, opt_value in opts: + if opt in ('-h', '--help'): + print("[*] Help info") + exit() + elif opt == '-i': + print('Test ID:', opt_value) + id = (int)(opt_value) + + x_values = ['10%', '20%', '30%', '40%', '50%'] # sorting step size + + y_values, max_value = ReadFile(id) # 55 + + # y_norm_values = normalize(y_values) + + # break into 4 parts + legend_labels = ['sort', 'merge', 'join'] # , 'others' + + DrawFigure(x_values, y_values, legend_labels, + 'sorting step size', 'cycles per input tuple', + 'breakdown_sort_figure', True) + + # DrawLegend(legend_labels, 'breakdown_radix_legend') + + +def DrawPercentageFigure(x_values, y_values, legend_labels, x_label, y_label, filename, allow_legend, title): + # you may change the figure size on your own. + fig = plt.figure(figsize=(9, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.5 + # draw the bars + bottom_base = np.zeros(len(y_values[0])) + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + width / 2, y_values[i], width, hatch=PATTERNS[i], color=LINE_COLORS[i], + label=FIGURE_LABEL[i], bottom=bottom_base, edgecolor='black', linewidth=3) + bottom_base = np.array(y_values[i]) + bottom_base + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL + # mode='expand', + # shadow=False, + # columnspacing=0.25, + # labelspacing=-2.2, + # borderpad=5, + # bbox_transform=ax.transAxes, + # frameon=False, + # columnspacing=5.5, + # handlelength=2, + ) + if allow_legend == True: + handles, labels = figure.get_legend_handles_labels() + if allow_legend == True: + print(handles[::-1], labels[::-1]) + leg = plt.legend(handles[::-1], labels[::-1], + loc='center', + prop=LEGEND_FP, + ncol=3, + bbox_to_anchor=(0.5, 1.2), + handletextpad=0.1, + borderaxespad=0.0, + handlelength=1.8, + labelspacing=0.3, + columnspacing=0.3, + ) + leg.get_frame().set_linewidth(2) + leg.get_frame().set_edgecolor("black") + + # sometimes you may not want to draw legends. + # if allow_legend == True: + # leg=plt.legend(bars, + # FIGURE_LABEL, + # prop=LEGEND_FP, + # loc='right', + # ncol=1, + # # mode='expand', + # bbox_to_anchor=(0.45, 1.1), shadow=False, + # columnspacing=0.1, + # frameon=True, borderaxespad=0.0, handlelength=1.5, + # handletextpad=0.1, + # labelspacing=0.1) + # leg.get_frame().set_linewidth(2) + # leg.get_frame().set_edgecolor("black") + + plt.ylim(0, 100) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 0.5 * width, x_values) + plt.xticks(rotation=30) + + # plt.xlim(0,) + # plt.ylim(0,1) + + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(6)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + plt.savefig(filename + ".pdf", bbox_inches='tight', format='pdf') diff --git a/benchmark/scripts/scanAlgoDelta/autoParase.py b/benchmark/scripts/scanAlgoDelta/autoParase.py new file mode 100755 index 00000000..9375c8e0 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/autoParase.py @@ -0,0 +1,87 @@ +import csv + + +def paraseValidStageNames(a): + nameList = [] + with open(a, 'r') as f: + reader = csv.reader(f) + # reader = [each for each in csv.DictReader(f, delimiter=',')] + result = list(reader) + rows = len(result) + # print('rows=',rows) + firstRow = result[0] + # print(firstRow) + index = 0 + # define what may attract our interest + idxCpu = 0 + idxName = 0 + for i in firstRow: + # print(i) + if (i == 'cpu'): + idxCpu = index + if (i == 'name'): + idxName = index + index = index + 1 + # read the valid stages + vdataEntries = 0 + + for k in range(1, rows): + if (result[k][idxCpu] != 'NA'): + R1 = ((result[k][idxName])) + nameList.append(R1) + return nameList + + +def paraseValidColums(a, nameList, colTitle): + with open(a, 'r') as f: + reader = csv.reader(f) + # reader = [each for each in csv.DictReader(f, delimiter=',')] + result = list(reader) + rows = len(result) + # print('rows=',rows) + firstRow = result[0] + # print(firstRow) + index = 0 + # define what may attract our interest + idxCpu = 0 + idxName = 0 + idxTitle = 0 + for i in firstRow: + # print(i) + if (i == 'cpu'): + idxCpu = index + if (i == 'name'): + idxName = index + if (i == colTitle): + idxTitle = index + index = index + 1 + # read the valid stages + vdataEntries = 0 + ru = [] + for k in range(1, rows): + if (result[k][idxCpu] != 'NA'): + R1 = ((result[k][idxName])) + for j in range(len(nameList)): + if (R1 == nameList[j]): + s = int(result[k][idxTitle]) + ru.append(s) + break + return ru + + +def maxInList(a): + # a in [[1,2] [3,4]] + inLen = len(a[0]) + ru = [] + index = [] + ti = 0 + for i in range(len(a[0])): + ts = 0 + ti = 0 + for k in range(len(a)): + if (a[k][i] > ts): + ts = a[k][i] + ti = k + ru.append(ts) + index.append(ti) + return ru, index diff --git a/benchmark/scripts/scanAlgoDelta/config_CPPTOW.csv b/benchmark/scripts/scanAlgoDelta/config_CPPTOW.csv new file mode 100644 index 00000000..5bd39217 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/config_CPPTOW.csv @@ -0,0 +1,11 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/TugOfWar.pt,String +useCPP,1,U64 +cppAlgoTag,tugOfWar,String +threads,1,U64 +forceMP,1,U64 +algoDelta,0.02,Double diff --git a/benchmark/scripts/scanAlgoDelta/config_RAWMM.csv b/benchmark/scripts/scanAlgoDelta/config_RAWMM.csv new file mode 100644 index 00000000..a1e0fe71 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/config_RAWMM.csv @@ -0,0 +1,9 @@ +key,value,type +aRow,1000,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/RAWMM.pt,String +threads,1,U64 +forceMP,1,U64 +algoDelta,0.02,Double diff --git a/benchmark/scripts/scanAlgoDelta/drawTogether.py b/benchmark/scripts/scanAlgoDelta/drawTogether.py new file mode 100755 index 00000000..aefede61 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/drawTogether.py @@ -0,0 +1,177 @@ +#!/usr/bin/env python3 +import csv +import numpy as np +import accuBar as accuBar +import groupBar as groupBar +import groupBar2 as groupBar2 +import groupLine as groupLine +from autoParase import * +import itertools as it +import os + +import matplotlib +import numpy as np +import pylab +import matplotlib.font_manager as fm +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator +import os +import pandas as pd +import sys +from OoOCommon import * +import time + +# OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 22 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['*', '|', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#FFFFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = (["////", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +scanTag = "algoDelta" + + +def singleRun(exePath, singleValue, resultPath, configTemplate): + # resultFolder="singleValueTests" + configFname = "config_" + scanTag + str(singleValue) + ".csv" + # configTemplate = "config.csv" + # clear old files + os.system("cd " + exePath + "&& sudo rm *.csv") + + # editConfig(configTemplate, exePath + configFname, "earlierEmitMs", 0) + editConfig(configTemplate, exePath + configFname, scanTag, singleValue) + # prepare new file + # run + os.system("cd " + exePath + "&& sudo ./benchmark " + configFname) + # copy result + os.system("sudo rm -rf " + resultPath + "/" + str(singleValue)) + os.system("sudo mkdir " + resultPath + "/" + str(singleValue)) + os.system("cd " + exePath + "&& sudo cp *.csv " + resultPath + "/" + str(singleValue)) + + +def runScanVector(exePath, singleValueVec, resultPath, templateName="config.csv"): + for i in singleValueVec: + singleRun(exePath, i, resultPath, templateName) + +def readResultSingle(singleValue, resultPath): + resultFname = resultPath + "/" + str(singleValue) + "/default.csv" + elapsedTime = readConfig(resultFname, "perfElapsedTime") + cacheMiss = readConfig(resultFname, "cacheMiss") + cacheRefs = readConfig(resultFname, "cacheRefs") + froError = readConfig(resultFname, "froError") + errorBoundRatio = readConfig(resultFname, "errorBoundRatio") + return elapsedTime, cacheMiss, cacheRefs, froError, errorBoundRatio + + +def cleanPath(path): + os.system("sudo rm -rf " + path) + os.system("sudo mkdir " + path) + + +def readResultVector(singleValueVec, resultPath): + elapseTimeVec = [] + cacheMissVec = [] + cacheRefVec = [] + froErrorVec = [] + errorBoundRatioVec = [] + for i in singleValueVec: + elapsedTime, cacheMiss, cacheRefs, froError, errorBoundRatio = readResultSingle(i, resultPath) + elapseTimeVec.append(float(elapsedTime) / 1000.0) + cacheMissVec.append(float(cacheMiss)) + cacheRefVec.append(float(cacheRefs)) + froErrorVec.append(float(froError)) + errorBoundRatioVec.append(float(errorBoundRatio)) + return np.array(elapseTimeVec), np.array(cacheMissVec), np.array(cacheRefVec), np.array(froErrorVec), np.array( + errorBoundRatioVec) + + +def compareMethod(exeSpace, commonPathBase, resultPaths, csvTemplates, periodVec, reRun=1): + elapsedTimeAll = [] + cacheMissAll = [] + cacheRefAll = [] + periodAll = [] + froAll = [] + errorBoundRatioAll = [] + for i in range(len(csvTemplates)): + resultPath = commonPathBase + resultPaths[i] + if (reRun == 1): + os.system("sudo rm -rf " + resultPath) + os.system("sudo mkdir " + resultPath) + runScanVector(exeSpace, periodVec, resultPath, csvTemplates[i]) + elapsedTime, cacheMiss, cacheRef, fro, eb = readResultVector(periodVec, resultPath) + elapsedTimeAll.append(elapsedTime) + cacheMissAll.append(cacheMiss) + cacheRefAll.append(cacheRef) + periodAll.append(periodVec) + cacheMissRateAll = np.array(cacheMissAll) / np.array(cacheRefAll) * 100.0 + froAll.append(fro) + errorBoundRatioAll.append(eb) + # periodAll.append(periodVec) + return np.array(elapsedTimeAll), cacheMissRateAll, periodAll, np.array(froAll), np.array(errorBoundRatioAll) + + +def main(): + exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" + commonBase = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/" + figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag + methodTags = ["TOW", "MM"] + resultPaths = ["tow", "mm"] + csvTemplates = ["config_CPPTOW.csv", "config_RAWMM.csv"] + valueVec = [0.2, 0.1, 0.02, 0.005, 5e-4, 2e-9, 9e-14, 2e-22, 3e-44] + valueVecDisp = np.array(valueVec) + # run + reRun = 0 + if (len(sys.argv) < 2): + os.system("mkdir ../../results") + os.system("mkdir ../../figures") + os.system("mkdir " + figPath) + os.system("sudo rm -rf " + commonBase) + os.system("sudo mkdir " + commonBase) + reRun = 1 + + elapsedTimeAll, cacheMissAll, periodAll, fro, eb = compareMethod(exeSpace, commonBase, resultPaths, csvTemplates, valueVec, + reRun) + groupLine.DrawFigure(periodAll, elapsedTimeAll, + methodTags, + "value of delta", "elapsed time (ms)", 0, 1, + figPath + "/" + scanTag + "_elapsedTime", + True) + groupLine.DrawFigureYnormal(periodAll, cacheMissAll, + methodTags, + "value of delta", "cacheMiss (%)", 0, 1, + figPath + "/" + scanTag + "_cacheMiss", + True) + + groupLine.DrawFigureYnormal(periodAll, + fro * 100.0, + methodTags, + "value of delta", "normalized error %", 0, 1, figPath + "/" +scanTag + "_froError", + True) + groupLine.DrawFigureYnormal(periodAll, + eb * 100.0, + methodTags, + "value of delta", "error bound ratio %", 0, 1, figPath + "/" + scanTag + "_ebRatio", + True) + +if __name__ == "__main__": + main() diff --git a/benchmark/scripts/scanAlgoDelta/groupBar.py b/benchmark/scripts/scanAlgoDelta/groupBar.py new file mode 100755 index 00000000..ef2d9842 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/groupBar.py @@ -0,0 +1,236 @@ +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 15 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (["", 'o', 's', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#7FFFFF', '#B03A2E', '#2874A6', '#FFFFFF', '#7FFFFF', '#B03A2E', '#2874A6', '#FFFFFF', '#F5CBA7', '#82E0AA', + '#AEB6BF', + '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = ( + ["////", "\\\\", "//", "o", "*", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + figlegend = pylab.figure(figsize=(16, 0.5)) + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], + edgecolor='black', linewidth=3) + + # LEGEND + + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=True, \ + frameon=True, handlelength=2, handletextpad=0.3, columnspacing=0.5, + borderaxespad=-0.2, fancybox=True + ) + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +# draw a bar chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.08 + # draw the bars + bars = [] + ts = 0 + pos = 0 + gl = len(y_values[0]) + for i in range(len(y_values)): + pos = pos + 3 * width + for j in range(len(y_values[i])): + pos = pos + width + bar = plt.bar(pos, y_values[i][j], width, hatch=PATTERNS[j], color=LINE_COLORS[j], label=FIGURE_LABEL[j], + edgecolor='black', linewidth=3) + bars.append(bar) + ts = ts + 1 + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL, + prop=LEGEND_FP, + ncol=4, + loc='upper center', + # mode='expand', + shadow=False, + bbox_to_anchor=(0.45, 1.6), + columnspacing=0.1, + handletextpad=0.2, + # bbox_transform=ax.transAxes, + # frameon=True, + # columnspacing=5.5, + # handlelength=2, + ) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index, x_values) + # plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + # plt.grid(axis='y', color='gray') + # figure.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) + + # you may need to tune the xticks position to get the best figure. + # plt.yscale('log') + # + # plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(5)) + # figure.xaxis.set_major_locator(LinearLocator(5)) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + plt.ylim(y_min, y_max) + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + col9 = [] + + for id in it.chain(range(38, 42)): + col9.append(0) + y.append(col9) # this is a lz4_pipe2 empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col1.append(x) + y.append(col1) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col2.append(x) + y.append(col2) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col3.append(x) + y.append(col3) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col4.append(x) + y.append(col4) + + y.append(col9) # this is a lz4_pipe2 empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col5.append(x) + y.append(col5) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col6.append(x) + y.append(col6) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col7.append(x) + y.append(col7) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col8.append(x) + y.append(col8) + return y + + +if __name__ == "__main__": + x_values = ["Stock", "Rovio", "YSB", "DEBS"] + + y_values = ReadFile() + + legend_labels = ['Lazy:', 'NPJ', 'PRJ', 'MWAY', 'MPASS', + 'Eager:', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', 'PMJ$^{JB}$'] + print(y_values) + DrawFigure(x_values, y_values, legend_labels, + '', 'Latency (ms)', 0, + 400, 'latency_figure_app', False) + + # DrawLegend(legend_labels, 'latency_legend') diff --git a/benchmark/scripts/scanAlgoDelta/groupBar2.py b/benchmark/scripts/scanAlgoDelta/groupBar2.py new file mode 100755 index 00000000..31155695 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/groupBar2.py @@ -0,0 +1,232 @@ +import itertools as it +import os + +import matplotlib +import matplotlib.pyplot as plt +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LogLocator, LinearLocator + +OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 24 +LABEL_FONT_SIZE = 28 +LEGEND_FONT_SIZE = 30 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (["", 'o', 's', 'v', "^", "", "h", "<", ">", "+", "d", "<", "|", "", "+", "_"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#FFFFFF', '#B03A2E', '#2874A6', '#239B56', '#7D3C98', '#00FFFF', '#F1C40F', '#F5CBA7', '#82E0AA', '#AEB6BF', + '#AA4499') +# you may want to change the patterns for different figures +PATTERNS = ( + ["", "////", "\\\\", "//", "o", "", "||", "-", "//", "\\", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", + "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 15.0 +MARKER_FREQUENCY = 1000 + +matplotlib.rcParams['ps.useafm'] = True +matplotlib.rcParams['pdf.use14corefonts'] = True +matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +matplotlib.rcParams['font.family'] = OPT_FONT_NAME +matplotlib.rcParams['pdf.fonttype'] = 42 + +exp_dir = "/data1/xtra" + +FIGURE_FOLDER = exp_dir + '/results/figure' + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LEGEND_FP = FontProperties(style='normal', size=26) + figlegend = pylab.figure(figsize=(16, 0.5)) + bars = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + width = 0.3 + for i in range(len(FIGURE_LABEL)): + bars[i] = ax1.bar(x_values, data, width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], + edgecolor='black', linewidth=3) + + # LEGEND + + figlegend.legend(bars, FIGURE_LABEL, prop=LEGEND_FP, \ + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=True, \ + frameon=True, handlelength=2, handletextpad=0.3, columnspacing=0.5, + borderaxespad=-0.2, fancybox=True + ) + figlegend.savefig(FIGURE_FOLDER + '/' + filename + '.pdf') + + +# draw a bar chart +def DrawFigure(x_values, y_values, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + # values in the x_xis + index = np.arange(len(x_values)) + # the bar width. + # you may need to tune it to get the best figure. + width = 0.12 + # draw the bars + bars = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + bars[i] = plt.bar(index + i * width + width / 2, + y_values[i], width, + hatch=PATTERNS[i], + color=LINE_COLORS[i], + label=FIGURE_LABEL[i], edgecolor='black', linewidth=3) + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(bars, FIGURE_LABEL, + prop=LEGEND_FP, + ncol=3, + loc='upper center', + # mode='expand', + shadow=False, + bbox_to_anchor=(0.45, 1.7), + columnspacing=0.1, + handletextpad=0.2, + # bbox_transform=ax.transAxes, + # frameon=True, + # columnspacing=5.5, + # handlelength=2, + ) + + # you may need to tune the xticks position to get the best figure. + plt.xticks(index + 3 * width, x_values, rotation=30) + + # plt.ticklabel_format(axis="y", style="sci", scilimits=(0, 0)) + # plt.grid(axis='y', color='gray') + # figure.get_xaxis().set_major_formatter(matplotlib.ticker.ScalarFormatter()) + + # you may need to tune the xticks position to get the best figure. + # plt.yscale('log') + # + # plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LinearLocator(10)) + # figure.xaxis.set_major_locator(LinearLocator(5)) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + col9 = [] + + for id in it.chain(range(38, 42)): + col9.append(0) + y.append(col9) # this is a fake empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col1.append(x) + y.append(col1) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col2.append(x) + y.append(col2) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col3.append(x) + y.append(col3) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get the 99th timestamp + col4.append(x) + y.append(col4) + + y.append(col9) # this is a fake empty line to separate eager and lazy. + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col5.append(x) + y.append(col5) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col6.append(x) + y.append(col6) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col7.append(x) + y.append(col7) + + for id in it.chain(range(38, 42)): + file = exp_dir + '/results/latency/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(int(len(read) * 0.95)).strip("\n")) # get last timestamp + col8.append(x) + y.append(col8) + return y + + +if __name__ == "__main__": + x_values = ["Stock", "Rovio", "YSB", "DEBS"] + + y_values = ReadFile() + + legend_labels = ['Lazy:', 'NPJ', 'PRJ', 'MWAY', 'MPASS', + 'Eager:', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', 'PMJ$^{JB}$'] + print(y_values) + DrawFigure(x_values, y_values, legend_labels, + '', 'Latency (ms)', 0, + 400, 'latency_figure_app', False) + + # DrawLegend(legend_labels, 'latency_legend') diff --git a/benchmark/scripts/scanAlgoDelta/groupLine.py b/benchmark/scripts/scanAlgoDelta/groupLine.py new file mode 100755 index 00000000..8110fd3b --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/groupLine.py @@ -0,0 +1,366 @@ +import itertools as it +import os +import matplotlib.pyplot as plt +import matplotlib.font_manager as fm +import matplotlib +import numpy as np +import pylab +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import MaxNLocator +from matplotlib.font_manager import FontProperties +from matplotlib.ticker import LinearLocator, LogLocator, MaxNLocator, ScalarFormatter +from numpy import double + +# 获取系统中可用的字体路径 +# font_paths = fm.findSystemFonts() +# OPT_FONT_NAME = 'Helvetica' +TICK_FONT_SIZE = 20 +LABEL_FONT_SIZE = 20 +LEGEND_FONT_SIZE = 20 +LABEL_FP = FontProperties(style='normal', size=LABEL_FONT_SIZE) +LEGEND_FP = FontProperties(style='normal', size=LEGEND_FONT_SIZE) +TICK_FP = FontProperties(style='normal', size=TICK_FONT_SIZE) + +MARKERS = (['o', 's', 'v', "^", "h", "v", ">", "x", "d", "<", "|", "p", "+", "_", "%", "|", "|", "|", "|", "|"]) +# you may want to change the color map for different figures +COLOR_MAP = ( + '#F15854', '#5DA5DA', '#60BD68', '#B276B2', '#DECF3F', '#F17CB0', '#B2912F', '#FAA43A', '#AFAFAF', '#087878', + '#783456', + '#560012', '#431256', "#00AABB", "#AA00BB") +# you may want to change the patterns for different figures +PATTERNS = (["|", "\\", "/", "+", "-", ".", "*", "x", "o", "O", "////", ".", "|||", "o", "---", "+", "\\\\", "*"]) +LABEL_WEIGHT = 'bold' +LINE_COLORS = COLOR_MAP +LINE_WIDTH = 3.0 +MARKER_SIZE = 13.0 +MARKER_FREQUENCY = 1000 + +# matplotlib.rcParams['ps.useafm'] = True +# matplotlib.rcParams['pdf.use14corefonts'] = True +# matplotlib.rcParams['xtick.labelsize'] = TICK_FONT_SIZE +# matplotlib.rcParams['ytick.labelsize'] = TICK_FONT_SIZE +# 创建字体列表 +# Explicitly specify the font path +# 获取系统中可用的字体路径 +font_paths = fm.findSystemFonts() + +# 创建字体列表 +font_list = [] +for font_path in font_paths: + try: + font_name = fm.FontProperties(fname=font_path).get_name() + if font_name not in font_list: + font_list.append(font_name) + except: + pass + +# 配置 matplotlib 使用系统中可用的字体 +plt.rcParams['font.family'] = font_list[0] + +FIGURE_FOLDER = '/data1/xtra/results/figure' + + +# there are some embedding problems if directly exporting the pdf figure using matplotlib. +# so we generate the eps format first and convert it to pdf. +def ConvertEpsToPdf(dir_filename): + os.system("epstopdf --outfile " + dir_filename + ".pdf " + dir_filename + ".eps") + os.system("rm -rf " + dir_filename + ".eps") + + +def DrawLegend(legend_labels, filename): + fig = pylab.figure() + ax1 = fig.add_subplot(111) + FIGURE_LABEL = legend_labels + LINE_WIDTH = 8.0 + MARKER_SIZE = 12.0 + LEGEND_FP = FontProperties(style='normal', size=26) + + figlegend = pylab.figure(figsize=(12, 0.5)) + idx = 0 + lines = [None] * (len(FIGURE_LABEL)) + data = [1] + x_values = [1] + + idx = 0 + for group in range(len(FIGURE_LABEL)): + lines[idx], = ax1.plot(x_values, data, + color=LINE_COLORS[idx], linewidth=LINE_WIDTH, + marker=MARKERS[idx], markersize=MARKER_SIZE, label=str(group)) + idx = idx + 1 + + # LEGEND + figlegend.legend(lines, FIGURE_LABEL, prop=LEGEND_FP, + loc=1, ncol=len(FIGURE_LABEL), mode="expand", shadow=False, + frameon=False, borderaxespad=0.0, handlelength=2) + + if not os.path.exists(FIGURE_FOLDER): + os.makedirs(FIGURE_FOLDER) + # no need to export eps in this case. + figlegend.savefig(filename + '.pdf') + + +# draw a line chart +def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i]) + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + # mode='expand', + bbox_to_anchor=(0.55, 1.6), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0.0, handlelength=1.5, + handletextpad=0.1, + labelspacing=0.1) + plt.xscale('log') + plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + figure.yaxis.set_major_locator(LogLocator(base=10)) + figure.xaxis.set_major_locator(LogLocator(base=10)) + + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# draw a line chart +def DrawFigureXYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i], markeredgecolor='k') + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + bbox_to_anchor=(0.55, 1.5), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + # plt.xscale('log') + # plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.xaxis.set_major_locator(LogLocator(base=10)) + plt.xticks(rotation=0, fontsize=TICK_FONT_SIZE) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# draw a line chart +def DrawFigureYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, filename, allow_legend): + # you may change the figure size on your own. + fig = plt.figure(figsize=(10, 3)) + figure = fig.add_subplot(111) + + FIGURE_LABEL = legend_labels + + x_values = xvalues + y_values = yvalues + + lines = [None] * (len(FIGURE_LABEL)) + for i in range(len(y_values)): + lines[i], = figure.plot(x_values[i], y_values[i], color=LINE_COLORS[i], \ + linewidth=LINE_WIDTH, marker=MARKERS[i], \ + markersize=MARKER_SIZE, label=FIGURE_LABEL[i], markeredgecolor='k') + + # sometimes you may not want to draw legends. + if allow_legend == True: + plt.legend(lines, + FIGURE_LABEL, + prop=LEGEND_FP, + loc='upper center', + ncol=3, + bbox_to_anchor=(0.55, 1.5), shadow=False, + columnspacing=0.1, + frameon=True, borderaxespad=0, handlelength=1.2, + handletextpad=0.1, + labelspacing=0.1) + plt.xscale('log') + # plt.yscale('log') + # plt.yscale('log') + + # you may control the limits on your own. + + # plt.ylim(y_min, y_max) + + plt.grid(axis='y', color='gray') + plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 + # figure.yaxis.set_major_locator(LogLocator(base=10)) + # figure.xaxis.set_major_locator(LogLocator(base=10)) + plt.xticks(rotation=0, fontsize=TICK_FONT_SIZE) + figure.get_xaxis().set_tick_params(direction='in', pad=10) + figure.get_yaxis().set_tick_params(direction='in', pad=10) + + plt.xlabel(x_label, fontproperties=LABEL_FP) + plt.ylabel(y_label, fontproperties=LABEL_FP) + + size = fig.get_size_inches() + dpi = fig.get_dpi() + + # plt.show() + plt.savefig(filename + ".pdf", bbox_inches='tight') + + +# example for reading csv file +def ReadFile(): + y = [] + col1 = [] + col2 = [] + col3 = [] + col4 = [] + col5 = [] + col6 = [] + col7 = [] + col8 = [] + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PRJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col1.append(value) + y.append(col1) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/NPJ_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col2.append(value) + y.append(col2) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/MPASS_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col3.append(value) + y.append(col3) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/MWAY_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col4.append(value) + y.append(col4) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/SHJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col5.append(value) + y.append(col5) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/SHJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col6.append(value) + y.append(col6) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PMJ_JM_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col7.append(value) + y.append(col7) + + for id in it.chain(range(28, 32)): + file = '/data1/xtra/results/timestamps/PMJ_JBCR_NP_{}.txt'.format(id) + f = open(file, "r") + read = f.readlines() + x = float(read.pop(len(read) - 1).strip("\n")) # get last timestamp + value = len(read) / x # get throughput (#items/ms) + col8.append(value) + y.append(col8) + return y + + +if __name__ == "__main__": + # x_values = ['Unique', 'Zipf(0)', 'Zipf(0.2)', 'Zipf(0.4)', 'Zipf(0.8)', 'Zipf(1)'] + x_values = [1600, 3200, 6400, 12800, 25600] + + y_values = ReadFile() + + legend_labels = ['NPJ', 'PRJ', 'MWAY', 'MPASS', 'SHJ$^{JM}$', 'SHJ$^{JB}$', 'PMJ$^{JM}$', + 'PMJ$^{JB}$'] + + DrawFigure(x_values, y_values, legend_labels, + 'Input arrival rate of R (e/ms)', 'Tpt. (#matches/ms)', x_values[0], + x_values[4], 'throughput_figure1_1', False) + +# DrawLegend(legend_labels, 'factor_legend') diff --git a/benchmark/scripts/scanAlgoDelta/perfRu.csv b/benchmark/scripts/scanAlgoDelta/perfRu.csv new file mode 100644 index 00000000..9ee43623 --- /dev/null +++ b/benchmark/scripts/scanAlgoDelta/perfRu.csv @@ -0,0 +1,7 @@ +key,value,type +cacheMiss,12491377,U64 +cacheRefs,35327177,U64 +cpuClock,2478812100,U64 +cpuCycle,9889422467,U64 +instructions,16997458033,U64 +taskClock,2478813000,U64 diff --git a/figures/algoBeta/algoBeta_cacheMiss.pdf b/figures/algoBeta/algoBeta_cacheMiss.pdf new file mode 100644 index 0000000000000000000000000000000000000000..f59eaf14da0c3235645ba0a0c1341e1a71df03f0 GIT binary patch literal 7700 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 QAt{ZNV&vynzNo_ZKY1i6DgXcg literal 0 HcmV?d00001 diff --git a/figures/algoBeta/algoBeta_elapsedTime.pdf b/figures/algoBeta/algoBeta_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e20e820412f899e58d839694361a54b8f409318a GIT binary patch literal 7725 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 literal 0 HcmV?d00001 diff --git a/figures/algoBeta/algoBeta_froError.pdf b/figures/algoBeta/algoBeta_froError.pdf new file mode 100644 index 0000000000000000000000000000000000000000..189352e2d0032ec8210c229b6c6dced6a0e94ec4 GIT binary patch literal 7522 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 literal 0 HcmV?d00001 diff --git a/figures/algoDelta/algoDelta_cacheMiss.pdf b/figures/algoDelta/algoDelta_cacheMiss.pdf new file mode 100644 index 0000000000000000000000000000000000000000..9ae6e51181b6cfaa9bc6d5a5e922fe9de88bc615 GIT binary patch literal 8432 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 F{{d=bm-7Gs literal 0 HcmV?d00001 diff --git a/figures/algoDelta/algoDelta_elapsedTime.pdf b/figures/algoDelta/algoDelta_elapsedTime.pdf new file mode 100644 index 0000000000000000000000000000000000000000..1892bda3bd8f439f2cd2b926bd10054737abdd5a GIT binary patch literal 8710 zcmb_?cUTi$(>J{Y=@Aqu5$P?JE+8GGcj<%>Ahb{d0s=~rB25uQI*JOSqM#s6y3(a8 zB8v2)fPi!<-v;&8_x5?O=l$c`Tx2(MW_QY&GiP>w@EfXWh{GjNApVCRAP=fRa0m>7 zcXR`tJ`I7I269@SU(5?U@(R#DuS?HPDDnTKW@;#dl4YWLk8$M z14lP3h5(WN@l!pJplL!t6R;4}4}u|@K*0KXK_rPkK~NJ{v=h$D1tRrx)EAF2!4e?W zfLJvRKox8t0Rq+b1XNJ@c~<>-)`r;rp$`0S1BiMPwfDsW+Wk-;YK-;6`}<-5dx-i2 z^7XJzIJ62r5ReE1K2j*8ge(M!L`lHl2tWW-6)+9B-wz`DLqTOPFFf!IPGtVm9mL^Z z{?o;Jxe#0-zypXpPz{_1U@>s^0NkL4#o(Q=M8*9GzF4#;C@}ktWe@(SG}BCN>prEq zfp=ii;_;EmQ^J(Av}R}cBy0==4GoPulAG#3;cIK`zIN87lIxkM$Bl-4{kG5*7&a^$ z^yFY?Ddb?G@Ba4mws+a-oQvGGLCK$P?Tv!uWYsX6sq< zT-(j`hK`$KD4&zK@d**lMvW*)74l#-1u<4LD41l#HILhZB1?$%yr>um!OB6QWM zdirLXB)(e)CqFS0ZWiv^mI`UHcL`uHuARL$$)b+vl~a?NO>dshu)-Thv&qUx%NS1D4!M$%s2l%Z$ z?9YDC{dyI1FXpBO!`-%hsSIv_DdwJum=;_FS5ZrzbX;Fq&neGqXC`cvcl7bUf1XMi{|Hh*XC;1+tpKx+t;{do#kAleQKku&8CvF!tS=c z7!A5xjoz8nHSD?XypgjuRV{Os%#YIDzL%{;TP$IIA}qDJ7W$T*A_tZ1-+QCeT(r37 zEnP*<%!{YXBr>DgRaG{N4;C5Mtuu6*w4`93t$S=0F`>nBWF}xmD>&VW0&$?RX*i3|~m>Qau#*!y~Dxu0Pp650sie)02vQ*2e zzV?-=P5VJzoss};0Nrbqt8ng_9Fp%)K>Z1HEN1t21Y~x4plEYqU`khnz3Y)nY7Bt+4CyCs}i{B0umo@Z!kt zPc!0wVRb6CI+{5si;vnA?2qX$Wfax=Dw{H-L2cod5uk1RI8;C_J1D$>-1)T#Pmx4K zjFCqz$^k*Ju^=r|)C>(3q=`W^RuoZvbT^vdiVqu{j!!wJN6t|$VUs|5E-^zvQPC0I zJE>uu#&Ov{tb^5)?Q&R_(RYWbotHFngH@kX^!0R$-QAt@hviA*HRY6ZCaZ@^K70@! z_Uv%%stx+Gm*e>U&B02-fu^P2dz!S261UHU(2bG!pv?VNu1A^a|z5X8damxLdM0vsX~+^4RZ7u2<$#^oXAH6;$u(_tIAq$B?D!2|Y#3rdle|Z>i!s zRL{`Msi{Y8ftd6J6$e%%8D2YEP73vTNX5;J3)N`1IDO#5B=BJb)R2}ME>^xbtLcwj z-wSY=eZ0M4_j_(h^E+{nH&0(lYp(PFpU!nA*Tq%e%5E2r*=r~1IcWFyA&cMpNw(U_>Luku`jh&;_ zc|zAjQJry0wFm>; z={9SSRABL;*}0_a+2|1IdUlW;i98uwrfpzhk?gg(g?vIT7QXUk$#_$xC?K7UO?kb^ zcyrS5MVqauMyRr#@cPlao%z8&cJRJ#<9TUyzjyeh#&y&+@1)ne{oh@zQT)wN+%d&V`-d`=bUfv&a z>quSv&0yK6H{^l|?ID7teIM($n5T4{%kqaHRP8Bzn_b@P9GTaZhE;8hvn?^qY!y1z zZ6(uWU#k1FEEaGCDl%?l9EQ{`x{uV7X_1pwLq#MZ2}%9-)cy1&x5esr>y3pM=i|!0 z&yV6?Ft?G0=5K!_xETx>o%lG=hR?353D3QI2AN&BN$(n^umJPf=Cjvl$s-(*Y67KX zqi2T&gs(Zpj9XV~WtMw$pTIf{oXogGl3qo@CB~X`JrUm3^vYEd(e`v|a@D5Fa{t8# zvVti@mHO+n&U1*R*>BruH_Wnl$E<8@xN`ty#~3*5a{E?swnR+BQIAHAt%%wpnb)dZ zoKceC_{&F|t#FB`biS|4Z12?Z@Wkg&LKk?|&tLJpq_cdwqu=yhs|0h&H*Y#AhkMU% z80U#io9uqQ`iL#Fp02~`eXH29C{&aaSYg}h*jxeZnmwrYQ65J<1)NZxYlSMd=c!=qpW8Mh{F4Oo%$Ne!Z40c@&D*OUGS{W} zmD9CvSc~wk2H9ll#IBB;xjjIE&>XE&69QLExe_DT770Nz-GX%Q&#KTHCI~-?Dw14g z;fz#UQ{l1%jlD^jcYw zp!dl@|7)q7taOgkaZ9yg&NyvFSq0cVInN1(ova%pPWGk_pB{Q7@zhwhpU5g&!fPw= z5JavPy)SY1<$9FFy>q5kRCf{?+0*MV`rg8YE>R;(vg~pH@MxbRS!zX6z_bQS{B_+c zvcotj;eHaqo8Z`FlMA@c+!q(-@n1*fbp^dXRh{xea^;<}YN2!!7t0vECN?bCp_W*5 z6zg%~fy0Agsr3c>yO<5w$Ee0JU(11BK^?_9J32*M!-QASOwDU&za-r2?RsdTH7qGt zv*#g5iK_iL+&B6@S53Ap3Dc?yH@)Gj@iH^;%Bf+nd*V@#>UZs{Va@l>b9!FEU6dm8ba&oos$;*TG3n!A~=iN=dPH&fPAGpjFd6B%KaVZn8Tb5e(EXVxW ztYWze_n;PcT_VBT?&7yTReqxhca{2>w>1g9j8QB@uqV-!LvxO93uwg$eT5?>rP~W5 zlP6HtkEp3Gk2H~pGgs^fyo|naEXVn3X4G<*-EK8W*x56h^0)3B5nA-*@?7jlmriZa zvD9{y$Ps+cHCb`N5!;6D>vFq>ncQL2iW7j`k8-2YnHLD7U=&1gGJTEvlKkQ+-?xuV zL!&{{y*h%qAJ30%Ck&nKe2u->e#D^Q)Qrbo;U`&67Y&&g{%?A??aYiT1a2Mp)a>nH zl$45>yo+#R4ehvXg4tz)a*`I!@kjMC8fa z6_=450e{;OtJdf8v^oyxX}@QcvxEFx4`Ui(N6W^2&QWG5pLiX8=AsmZ$*`Ez2y8?q zZ~Ey`4@oa44Xd+U@h_cB$|Og@_$zwKiC1rGF{ex9eBXyJ&DBPW=d^1^B~Rzx3jE@F zxi*|NgT%5V3Pyj-{m2;I(3Zz|3^)&MViW24pqZ)gsk&OsFic9IUs*Ht#w~Ggtr5AA zuyZ8om+Q_xRCjA++di%IxQ{zQkxhL12`5`&sZ~>rU(dtlb0OJLZaa-`;ej>5`IwyX z{>DPPz;R(WU1`6~uJh37B>9Rpk;#dXo|l^wR9VfuE=#X`3ODKlch=&+8)zTxrrmpa zeqttq)92e4=t~|l&5)Dw;74JPo--ATlbWu;I0dRWLum&{5}|T^E?%*ta${$V?Nyr` zvLqYXiVLh`N^*POwej8k=5e8Qc!MN+RDo^mRqsqSbp+;E&b25fm&#xnvJo*wiIZ3- zw{wrl7NIzuy<4j5>oJURs%G@P>ouac(R)bhmc^0hFBc2)(DjrzQZ7C`18s_%~9<*Pr82vQD6Y%;-``b_z zk6y;46B{x6F)C#jP0J}n*sJ&r-7l#n-4QqSTo1Q$v$!90fAQALEptuJ z_!$|SIu|bv(}uiZM1Ver@M4XEdNZ__8Q$TTFo4Igp;pkiAbyB5PN$$X>FJ*MisXBuVY>7DKZ zS<(BOSDlv+8r?tJKF*lJ@oyW8UgqsLpY$HcuJ6If8R@u=h7{8-PTjxc`o_x6AzJ=Y z?Eb}589BVx%5~|?&tqj6x5fGB{TB)Y5M<^ZLbn}*(^E{>tu(4%lIrNM<{S}L%6ucQ z`FZq+tpSzW_k;aoWZzY8zX28awt~h@h1JgReV}l?@wTdZiDu1u8OpHxlofwr#hhke z+aadmz<2EY$t_K2*q4T^EWy<*GJN35324Rl6?dh5M8ETk>>apI;hKgn7I=c-YcexbmD#iEo`zbjA1!IP5-) zb>Y}cM&51pa2~aZ?_{4?w|K}7Y#rj+q1nkZ>=e1luRh7FWH&sQ&fFT23K8Y(0i8az ztQU@_39%ikrw!2?s|SUcjp4!zb+^tYM%ME_*`C6UiY-sYafYp;a%}|jw#p;(+I;-S zY14Pzskzy=%Gi@>ciF@B$PO&Wbhvj5nRee8Q6HpHCrf2+8&OMTuB3z4pnHL8V^9ii zw!pRoYD(^RJWY%;J{M`~=9GEvZ`E!^G=yHD56NqILG|IOe8kt4u_as3C$8`s@Q33G zJ#-v84Uksw9Jr_!E^e){~VTmqa6dE;slp-PkT2Ozzw} z$NS`*!?gx%X{G5HiwTE)N_aAzSW(N%mMOX});Z=%tudAGrP7;UT3e6YJhjXm&Pdnw z8ZIX=fCqdc~^nX$dc zR*Mf2s_#jdY(2gmXkj6ggq%1Rj-g26#*P>4$%vSZ7l_@=yghp#bZ^eb2_Os8IOxYe2=$(MAMHIzcf{OK5EeTaLE$D|w34qI ziC82NO#xHxQQz?vX3mI!T$M!jyz=yDJBXp)?<3uPY%pj~>g@{J`wwrp|DpdZDf{1F zBNw}CXh|R>s*T|Nj~DH2n>3cjl&krY(*~cdCDhD%zEGqf`Jcz7o(1yL%p?kbtAHT3 zyZ`5#Ed(J2yx0D>{f_pQJ>EpVnmu__aJK9%~@F>E{)r!GIFydW*JB^!m+v?aw z`%oFL`)7hb)NCfzu)dIjCZ;gV)x3GAPOT#1<l(N_JgY*lb+yMgl3 zxJ~n(!A<@)*6iF&&1Ya?F>{^Le(deeGzs#YS<9kpW4X)B92Y8>f{)OBWNUDC-&^qc z;xh*;F|7QIE^2?$Bu^FMNtwwA@5XTUI_9RsFjEvOGMb)rw zXmfuPw3i0q+Ze|3q#qAP6D^1K=HiC{w(qwwfN= z8v_3UoBZy7!2iUJ{-aSuBJ96d^G{<1`b$%BEeMpT70~fPdl85_`T>y6p$m#_l`u$>6h93sr zk6Hf>3_?|viS}U75cpw$DI@+@HlXwNn+^HDvcV)|4jGAOMa4f{@ke{_cSsTg_@|1$ ziGQv=Js1T36W!DUO#A_4{$@QK`(@(~<9>mlzx#$7cwbK-dVU25TtX5e4kv#9{;~!A zY5~HL|A(~cc@@rZ335bzGxs+8Rw5;-CD#k8c=*cx0~Xa&9mYb77uPJd^W&te$!}9A zYV*t1R|>9AnE1kx5n>#s$Q~Bo!PCeE^R{A`dRjrF8{%W=x(EIqJdV`fN!02>&%;u~ zP3C=$gx)QKOPiNmO$xq6gj*hY9?`h7d}|W^g!K`Dv|vZa`adMCKPUYEi!*>&{;yjI z(y(m;VYoceFFAlTBVnzw@pfjoNsFH6y?NZmM&E`6nGA~lTh~7~tRJfWfV!bNIH$wx z@gt!fqQL&ZqCE`HpDks?pKCxBKyrz>P)H9=@b z{|rgseO-h>P(xq5lRpLkhX1_F+sPT?h{m`BQhq)GNWq7X$Kk!yh%ma4nj8X#K*FTp z2p9^5K)|hpLBC@$&=>0rfW`4J~lfspy@ zdD1A^zwMBg`ukoa;x8Fevc!r0pE9H*fu#O#nzZ!a_rhfV(glG+{Ov0^3dlD9l7aYJ z7a4%%Hy^Nlhxyo#fc7OEhKCGX5)R_$ JS2xfA{XbkBT{-{& literal 0 HcmV?d00001 diff --git a/figures/algoDelta/algoDelta_froError.pdf b/figures/algoDelta/algoDelta_froError.pdf new file mode 100644 index 0000000000000000000000000000000000000000..c971b4c66ad8dab333cdc2765ac0665d284ac0ab GIT binary patch literal 8344 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