diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9f93aca2..509cd206 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -44,4 +44,5 @@ jobs: # Execute tests defined by the CMake configuration. # See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail run: | - ./cpp_test "--success" \ No newline at end of file + ./cpp_test "--success" + ./sketch_test "--success" \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f979b51..26a43e4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,7 +67,7 @@ add_subdirectory(src) # Add Library get_sources(IntelliStream_SOURCE_FILES) get_headers(IntelliStream_HEADER_FILES) -add_library(IntelliStream SHARED ${IntelliStream_SOURCE_FILES} ${IntelliStream_HEADER_FILES} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) +add_library(IntelliStream SHARED ${IntelliStream_SOURCE_FILES} ${IntelliStream_HEADER_FILES} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}) set_property(TARGET IntelliStream PROPERTY CXX_STANDARD 20) target_include_directories(IntelliStream PUBLIC "include") diff --git a/Doxyfile b/Doxyfile index e127a34a..e0ed8eee 100755 --- a/Doxyfile +++ b/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = "AMMBench" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 0.1.0 +PROJECT_NUMBER = 0.1.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/README.md b/README.md index 952b6567..dd4d4210 100644 --- a/README.md +++ b/README.md @@ -198,6 +198,6 @@ You will find the figures then. 1. If you use Torch with cuda, the nvcc will refuse to work as it doesn't support c++20 yet. Therefore, we disabled the global requirement check of C++ 20, and only leave an "-std=c++20" option for g++. This will be fixed after nvidia can support c++20 in cuda. -2. Some pytorch version can not work well with liblog4cxx and googletest, so we diabled it. +2. Some pytorch version can not work well with liblog4cxx and googletest, so we diabled it. 3. Clion may fail to render and highlight the torch apis. In this case, kindly type a random line of "555" -to validate the highlight when you need it, and comment it during a compile. :) + to validate the highlight when you need it, and comment it during a compile. :) diff --git a/benchmark/scripts/scanARank/drawTogether.py b/benchmark/scripts/scanARank/drawTogether.py index 585f18d9..ec8c49c3 100755 --- a/benchmark/scripts/scanARank/drawTogether.py +++ b/benchmark/scripts/scanARank/drawTogether.py @@ -81,9 +81,12 @@ def readResultSingle(singleValue, resultPath): cacheRefs = readConfig(resultFname, "cacheRefs") return elapsedTime, cacheMiss, cacheRefs + def cleanPath(path): os.system("sudo rm -rf " + path) os.system("sudo mkdir " + path) + + def readResultVector(singleValueVec, resultPath): elapseTimeVec = [] cacheMissVec = [] @@ -99,14 +102,14 @@ def readResultVector(singleValueVec, resultPath): def main(): exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" resultPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag - resultPathFDAMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/FDAMM" - resultPathCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/CoFD" - resultPathBetaCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/BCoFD" - resultPathRAWMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/RAWMM" + resultPathFDAMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/FDAMM" + resultPathCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/CoFD" + resultPathBetaCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/BCoFD" + resultPathRAWMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/RAWMM" figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag configTemplate = exeSpace + "config.csv" - valueVec = [2,5,10,20,50,100,200,500,900] - valueVecRun = 1000-np.array(valueVec) + valueVec = [2, 5, 10, 20, 50, 100, 200, 500, 900] + valueVecRun = 1000 - np.array(valueVec) print(configTemplate) # run if (len(sys.argv) < 2): @@ -125,18 +128,20 @@ def main(): runScanVector(exeSpace, valueVecRun, resultPathCoFD, "config_CoAMM.csv") runScanVector(exeSpace, valueVecRun, resultPathBetaCoFD, "config_BCoAMM.csv") runScanVector(exeSpace, valueVecRun, resultPathRAWMM, "config_RAWMM.csv") - evaTypes=['FDAMM','MM','Co-FD','BCO-FD'] + evaTypes = ['FDAMM', 'MM', 'Co-FD', 'BCO-FD'] elapseTimeVecFD, cacheMissVecFD, cacheRefVecFD = readResultVector(valueVecRun, resultPathFDAMM) elapseTimeVecCoFD, cacheMissVecCoFD, cacheRefVecCoFD = readResultVector(valueVecRun, resultPathCoFD) elapseTimeVeCB, cacheMissVecB, cacheRefVecB = readResultVector(valueVecRun, resultPathBetaCoFD) elapseTimeVecRAW, cacheMissVecRAW, cacheRefVecRAW = readResultVector(valueVecRun, resultPathRAWMM) # os.system("mkdir " + figPath) - groupLine.DrawFigureYnormal([valueVec,valueVec,valueVec,valueVec], [elapseTimeVecFD,elapseTimeVecRAW,elapseTimeVecCoFD,elapseTimeVeCB], + groupLine.DrawFigureYnormal([valueVec, valueVec, valueVec, valueVec], + [elapseTimeVecFD, elapseTimeVecRAW, elapseTimeVecCoFD, elapseTimeVeCB], evaTypes, "Rank of matrix A", "elapsed time (ms)", 0, 1, figPath + "Rank" + "_elapsedTime", True) - groupLine.DrawFigureYnormal([valueVec,valueVec,valueVec,valueVec], [cacheMissVecFD/cacheRefVecFD*100.0,cacheMissVecRAW/cacheRefVecRAW*100.0, - cacheMissVecCoFD/cacheRefVecCoFD*100.0,cacheMissVecB/cacheRefVecB*100.0], + groupLine.DrawFigureYnormal([valueVec, valueVec, valueVec, valueVec], + [cacheMissVecFD / cacheRefVecFD * 100.0, cacheMissVecRAW / cacheRefVecRAW * 100.0, + cacheMissVecCoFD / cacheRefVecCoFD * 100.0, cacheMissVecB / cacheRefVecB * 100.0], evaTypes, "Rank of matrix A", "cacheMiss (%)", 0, 1, figPath + "Rank" + "_cacheMiss", True) @@ -146,7 +151,7 @@ def main(): # groupLine.DrawFigureYnormal([singleValueVec,singleValueVec],[errVec,aqpErrVec],['w/o aqp',"w/ MeanAqp"],"watermark time (ms)","Error",0,1,figPath+"wm_MeanAqp",True) # print(errVec) # print(aqpErrVec) - #print(elapseTimeVecFD) + # print(elapseTimeVecFD) # readResultsingleValue(50,resultPath) diff --git a/benchmark/scripts/scanARank/groupLine.py b/benchmark/scripts/scanARank/groupLine.py index 89020eff..8110fd3b 100755 --- a/benchmark/scripts/scanARank/groupLine.py +++ b/benchmark/scripts/scanARank/groupLine.py @@ -135,7 +135,7 @@ def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, # you may control the limits on your own. - #plt.ylim(y_min, y_max) + # plt.ylim(y_min, y_max) plt.grid(axis='y', color='gray') figure.yaxis.set_major_locator(LogLocator(base=10)) @@ -150,7 +150,7 @@ def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, size = fig.get_size_inches() dpi = fig.get_dpi() - #plt.show() + # plt.show() plt.savefig(filename + ".pdf", bbox_inches='tight') @@ -208,6 +208,7 @@ def DrawFigureXYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, # 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. @@ -262,6 +263,7 @@ def DrawFigureYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, # plt.show() plt.savefig(filename + ".pdf", bbox_inches='tight') + # example for reading csv file def ReadFile(): y = [] diff --git a/benchmark/scripts/scanARow/drawTogether.py b/benchmark/scripts/scanARow/drawTogether.py index 19f67ca0..f993cbd1 100755 --- a/benchmark/scripts/scanARow/drawTogether.py +++ b/benchmark/scripts/scanARow/drawTogether.py @@ -81,9 +81,12 @@ def readResultSingle(singleValue, resultPath): cacheRefs = readConfig(resultFname, "cacheRefs") return elapsedTime, cacheMiss, cacheRefs + def cleanPath(path): os.system("sudo rm -rf " + path) os.system("sudo mkdir " + path) + + def readResultVector(singleValueVec, resultPath): elapseTimeVec = [] cacheMissVec = [] @@ -99,13 +102,13 @@ def readResultVector(singleValueVec, resultPath): def main(): exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" resultPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag - resultPathFDAMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/FDAMM" - resultPathCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/CoFD" - resultPathBetaCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/BCoFD" - resultPathRAWMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/RAWMM" + resultPathFDAMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/FDAMM" + resultPathCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/CoFD" + resultPathBetaCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/BCoFD" + resultPathRAWMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/RAWMM" figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag configTemplate = exeSpace + "config.csv" - valueVec = [100, 200, 500, 1000, 2000, 5000, 10000, 20000,50000] + valueVec = [100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000] valueVecDisp = np.array(valueVec) print(configTemplate) # run @@ -125,18 +128,20 @@ def main(): runScanVector(exeSpace, valueVec, resultPathCoFD, "config_CoAMM.csv") runScanVector(exeSpace, valueVec, resultPathBetaCoFD, "config_BCoAMM.csv") runScanVector(exeSpace, valueVec, resultPathRAWMM, "config_RAWMM.csv") - evaTypes=['FDAMM','MM','Co-FD','BCO-FD'] + evaTypes = ['FDAMM', 'MM', 'Co-FD', 'BCO-FD'] elapseTimeVecFD, cacheMissVecFD, cacheRefVecFD = readResultVector(valueVec, resultPathFDAMM) elapseTimeVecCoFD, cacheMissVecCoFD, cacheRefVecCoFD = readResultVector(valueVec, resultPathCoFD) elapseTimeVeCB, cacheMissVecB, cacheRefVecB = readResultVector(valueVec, resultPathBetaCoFD) elapseTimeVecRAW, cacheMissVecRAW, cacheRefVecRAW = readResultVector(valueVec, resultPathRAWMM) # os.system("mkdir " + figPath) - groupLine.DrawFigure([valueVec,valueVec,valueVec,valueVec], [elapseTimeVecFD,elapseTimeVecRAW,elapseTimeVecCoFD,elapseTimeVeCB], - evaTypes, - "#elements in A's row", "elapsed time (ms)", 0, 1, figPath + scanTag + "_elapsedTime", - True) - groupLine.DrawFigureYnormal([valueVec,valueVec,valueVec,valueVec], [cacheMissVecFD/cacheRefVecFD*100.0,cacheMissVecRAW/cacheRefVecRAW*100.0, - cacheMissVecCoFD/cacheRefVecCoFD*100.0,cacheMissVecB/cacheRefVecB*100.0], + groupLine.DrawFigure([valueVec, valueVec, valueVec, valueVec], + [elapseTimeVecFD, elapseTimeVecRAW, elapseTimeVecCoFD, elapseTimeVeCB], + evaTypes, + "#elements in A's row", "elapsed time (ms)", 0, 1, figPath + scanTag + "_elapsedTime", + True) + groupLine.DrawFigureYnormal([valueVec, valueVec, valueVec, valueVec], + [cacheMissVecFD / cacheRefVecFD * 100.0, cacheMissVecRAW / cacheRefVecRAW * 100.0, + cacheMissVecCoFD / cacheRefVecCoFD * 100.0, cacheMissVecB / cacheRefVecB * 100.0], evaTypes, "#elements in A's row", "cacheMiss (%)", 0, 1, figPath + scanTag + "_cacheMiss", True) @@ -146,7 +151,7 @@ def main(): # groupLine.DrawFigureYnormal([singleValueVec,singleValueVec],[errVec,aqpErrVec],['w/o aqp',"w/ MeanAqp"],"watermark time (ms)","Error",0,1,figPath+"wm_MeanAqp",True) # print(errVec) # print(aqpErrVec) - #print(elapseTimeVecFD) + # print(elapseTimeVecFD) # readResultsingleValue(50,resultPath) diff --git a/benchmark/scripts/scanARow/groupLine.py b/benchmark/scripts/scanARow/groupLine.py index 89020eff..8110fd3b 100755 --- a/benchmark/scripts/scanARow/groupLine.py +++ b/benchmark/scripts/scanARow/groupLine.py @@ -135,7 +135,7 @@ def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, # you may control the limits on your own. - #plt.ylim(y_min, y_max) + # plt.ylim(y_min, y_max) plt.grid(axis='y', color='gray') figure.yaxis.set_major_locator(LogLocator(base=10)) @@ -150,7 +150,7 @@ def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, size = fig.get_size_inches() dpi = fig.get_dpi() - #plt.show() + # plt.show() plt.savefig(filename + ".pdf", bbox_inches='tight') @@ -208,6 +208,7 @@ def DrawFigureXYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, # 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. @@ -262,6 +263,7 @@ def DrawFigureYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, # plt.show() plt.savefig(filename + ".pdf", bbox_inches='tight') + # example for reading csv file def ReadFile(): y = [] diff --git a/benchmark/scripts/scanASparse/drawTogether.py b/benchmark/scripts/scanASparse/drawTogether.py index b138cf4d..0877fa08 100755 --- a/benchmark/scripts/scanASparse/drawTogether.py +++ b/benchmark/scripts/scanASparse/drawTogether.py @@ -81,9 +81,12 @@ def readResultSingle(singleValue, resultPath): cacheRefs = readConfig(resultFname, "cacheRefs") return elapsedTime, cacheMiss, cacheRefs + def cleanPath(path): os.system("sudo rm -rf " + path) os.system("sudo mkdir " + path) + + def readResultVector(singleValueVec, resultPath): elapseTimeVec = [] cacheMissVec = [] @@ -99,13 +102,13 @@ def readResultVector(singleValueVec, resultPath): def main(): exeSpace = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/" resultPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag - resultPathFDAMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/FDAMM" - resultPathCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/CoFD" - resultPathBetaCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/BCoFD" - resultPathRAWMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag+"/RAWMM" + resultPathFDAMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/FDAMM" + resultPathCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/CoFD" + resultPathBetaCoFD = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/BCoFD" + resultPathRAWMM = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/results/" + scanTag + "/RAWMM" figPath = os.path.abspath(os.path.join(os.getcwd(), "../..")) + "/figures/" + scanTag configTemplate = exeSpace + "config.csv" - valueVec = [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0] + valueVec = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0] valueVecDisp = np.array(valueVec) print(configTemplate) # run @@ -125,28 +128,30 @@ def main(): runScanVector(exeSpace, valueVec, resultPathCoFD, "config_CoAMM.csv") runScanVector(exeSpace, valueVec, resultPathBetaCoFD, "config_BCoAMM.csv") runScanVector(exeSpace, valueVec, resultPathRAWMM, "config_RAWMM.csv") - evaTypes=['FDAMM','MM','Co-FD','BCO-FD'] + evaTypes = ['FDAMM', 'MM', 'Co-FD', 'BCO-FD'] elapseTimeVecFD, cacheMissVecFD, cacheRefVecFD = readResultVector(valueVec, resultPathFDAMM) elapseTimeVecCoFD, cacheMissVecCoFD, cacheRefVecCoFD = readResultVector(valueVec, resultPathCoFD) elapseTimeVeCB, cacheMissVecB, cacheRefVecB = readResultVector(valueVec, resultPathBetaCoFD) elapseTimeVecRAW, cacheMissVecRAW, cacheRefVecRAW = readResultVector(valueVec, resultPathRAWMM) # os.system("mkdir " + figPath) - groupLine.DrawFigureXYnormal([valueVec,valueVec,valueVec,valueVec], [elapseTimeVecFD,elapseTimeVecRAW,elapseTimeVecCoFD,elapseTimeVeCB], - evaTypes, - "Density of matrix A", "elapsed time (ms)", 0, 1, figPath + scanTag + "_elapsedTime", - True) - groupLine.DrawFigureXYnormal([valueVec,valueVec,valueVec,valueVec], [cacheMissVecFD/cacheRefVecFD*100.0,cacheMissVecRAW/cacheRefVecRAW*100.0, - cacheMissVecCoFD/cacheRefVecCoFD*100.0,cacheMissVecB/cacheRefVecB*100.0], - evaTypes, - "Density of matrix A", "cacheMiss (%)", 0, 1, figPath + scanTag + "_cacheMiss", - True) + groupLine.DrawFigureXYnormal([valueVec, valueVec, valueVec, valueVec], + [elapseTimeVecFD, elapseTimeVecRAW, elapseTimeVecCoFD, elapseTimeVeCB], + evaTypes, + "Density of matrix A", "elapsed time (ms)", 0, 1, figPath + scanTag + "_elapsedTime", + True) + groupLine.DrawFigureXYnormal([valueVec, valueVec, valueVec, valueVec], + [cacheMissVecFD / cacheRefVecFD * 100.0, cacheMissVecRAW / cacheRefVecRAW * 100.0, + cacheMissVecCoFD / cacheRefVecCoFD * 100.0, cacheMissVecB / cacheRefVecB * 100.0], + evaTypes, + "Density of matrix A", "cacheMiss (%)", 0, 1, figPath + scanTag + "_cacheMiss", + 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") # draw2yLine("watermark time (ms)",singleValueVecDisp,lat95Vec,compVec,"95% Latency (ms)","Completeness","ms","",figPath+"wm_omp") # groupLine.DrawFigureYnormal([singleValueVec,singleValueVec],[errVec,aqpErrVec],['w/o aqp',"w/ MeanAqp"],"watermark time (ms)","Error",0,1,figPath+"wm_MeanAqp",True) # print(errVec) # print(aqpErrVec) - #print(elapseTimeVecFD) + # print(elapseTimeVecFD) # readResultsingleValue(50,resultPath) diff --git a/benchmark/scripts/scanASparse/groupLine.py b/benchmark/scripts/scanASparse/groupLine.py index 89020eff..8110fd3b 100755 --- a/benchmark/scripts/scanASparse/groupLine.py +++ b/benchmark/scripts/scanASparse/groupLine.py @@ -135,7 +135,7 @@ def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, # you may control the limits on your own. - #plt.ylim(y_min, y_max) + # plt.ylim(y_min, y_max) plt.grid(axis='y', color='gray') figure.yaxis.set_major_locator(LogLocator(base=10)) @@ -150,7 +150,7 @@ def DrawFigure(xvalues, yvalues, legend_labels, x_label, y_label, y_min, y_max, size = fig.get_size_inches() dpi = fig.get_dpi() - #plt.show() + # plt.show() plt.savefig(filename + ".pdf", bbox_inches='tight') @@ -208,6 +208,7 @@ def DrawFigureXYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, # 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. @@ -262,6 +263,7 @@ def DrawFigureYnormal(xvalues, yvalues, legend_labels, x_label, y_label, y_min, # plt.show() plt.savefig(filename + ".pdf", bbox_inches='tight') + # example for reading csv file def ReadFile(): y = [] diff --git a/benchmark/src/Benchmark.cpp b/benchmark/src/Benchmark.cpp index 7123c301..a47aabec 100644 --- a/benchmark/src/Benchmark.cpp +++ b/benchmark/src/Benchmark.cpp @@ -17,7 +17,9 @@ void runSingleThreadTest(std::string configName) { sketchDimension = cfg->tryU64("sketchDimension", 50, true); uint64_t coreBind = cfg->tryU64("coreBind", 0, true); UtilityFunctions::bind2Core((int) coreBind); + torch::set_num_threads(1); std::string ptFile = cfg->tryString("ptFile", "torchscripts/FDAMM.pt", true); + //uint64_t customResultName = cfg->tryU64("customResultName", 0, true); INTELLI_INFO("Place me at core" + to_string(coreBind)); INTELLI_INFO( diff --git a/benchmark/torchscripts/CountSketch.py b/benchmark/torchscripts/CountSketch.py index 84685928..fc890d98 100644 --- a/benchmark/torchscripts/CountSketch.py +++ b/benchmark/torchscripts/CountSketch.py @@ -12,8 +12,8 @@ def CountSketch(A: torch.Tensor, B: torch.Tensor, s: int): Ca = torch.zeros((m1, s)) Cb = torch.zeros((s, m2)) - L = torch.randint(s, (n, )) - G = torch.randint(2, (n, )) + L = torch.randint(s, (n,)) + G = torch.randint(2, (n,)) # modify the random column with random sign for i in range(0, n): diff --git a/benchmark/torchscripts/E2E_Minist.py b/benchmark/torchscripts/E2E_Minist.py index 3f3da3d8..234b5f45 100644 --- a/benchmark/torchscripts/E2E_Minist.py +++ b/benchmark/torchscripts/E2E_Minist.py @@ -5,15 +5,18 @@ import torchvision.transforms as transforms import os import CoOccurringFD + + # Define your custom matrix multiplication function def my_matmul(x, y): - rows,cols=x.shape - if cols>20: - sketchSize=cols/10 + rows, cols = x.shape + if cols > 20: + sketchSize = cols / 10 else: - sketchSize=10 + sketchSize = 10 # Your implementation here - return CoOccurringFD.FDAMM(x,y,int(sketchSize)) + return CoOccurringFD.FDAMM(x, y, int(sketchSize)) + # Define a custom Linear layer that uses your custom matrix multiplication function class CustomLinear(nn.Module): @@ -27,9 +30,11 @@ def __init__(self, in_features, out_features, bias=True): else: self.register_parameter('bias', None) self.reset_parameters() - def mySqrt(self,a:float): + + def mySqrt(self, a: float): y = torch.sqrt(torch.tensor(a, dtype=torch.float32)) return y.item() + def reset_parameters(self): nn.init.kaiming_uniform_(self.weight, a=self.mySqrt(5.0)) if self.bias is not None: @@ -44,6 +49,7 @@ def forward(self, input): output += self.bias return output + # Define your neural network architecture class MyNet(nn.Module): def __init__(self): @@ -51,36 +57,41 @@ def __init__(self): self.fc1 = nn.Linear(784, 128) self.fc2 = nn.Linear(128, 128) self.fc3 = nn.Linear(128, 10) + def forward(self, x): x = x.view(-1, 784) x = nn.functional.relu(self.fc1(x)) x = self.fc2(x) x = nn.functional.relu(self.fc3(x)) return x -def testNN(net,test_loader): - #first, load parameters - pretrained_params = torch.load('pretrained_model.pt') - custom_params = net.state_dict() - - for name in custom_params: - if name in pretrained_params: - custom_params[name] = pretrained_params[name] - net.load_state_dict(custom_params) - correct = 0 - total = 0 - #then, run test - net2=net - for data in test_loader: - images, labels = data - outputs = net2(images) - _, predicted = torch.max(outputs.data, 1) - total += labels.size(0) - correct += (predicted == labels).sum().item() - print(f"Accuracy on test set: {correct / total}") + + +def testNN(net, test_loader): + # first, load parameters + pretrained_params = torch.load('pretrained_model.pt') + custom_params = net.state_dict() + + for name in custom_params: + if name in pretrained_params: + custom_params[name] = pretrained_params[name] + net.load_state_dict(custom_params) + correct = 0 + total = 0 + # then, run test + net2 = net + for data in test_loader: + images, labels = data + outputs = net2(images) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() print(f"Accuracy on test set: {correct / total}") - return correct / total + print(f"Accuracy on test set: {correct / total}") + return correct / total + + def main(): - device='cuda' + device = 'cuda' # Load the MNIST dataset train_dataset = datasets.MNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True) test_dataset = datasets.MNIST(root='./data', train=False, transform=transforms.ToTensor()) @@ -96,51 +107,48 @@ def main(): if os.path.exists('pretrained_model.pt'): print('find pretrained model, run test') print('first run default version') - accuracy0=testNN(net,test_loader) + accuracy0 = testNN(net, test_loader) print('then run coocuuring 1 version') # Replace the Linear layers with your custom Linear layers and load the pre-trained weights net.fc1 = CustomLinear(784, 128) - accuracy1=testNN(net,test_loader) + accuracy1 = testNN(net, test_loader) print('next run coocuuring 2 version') - net.fc1=nn.Linear(784,128) + net.fc1 = nn.Linear(784, 128) net.fc2 = CustomLinear(128, 128) - accuracy2=testNN(net,test_loader) + accuracy2 = testNN(net, test_loader) print('finally run coocuuring 3 version') net.fc2 = nn.Linear(128, 128) net.fc3 = CustomLinear(128, 10) - accuracy3=testNN(net,test_loader) - print('default accuracy=',accuracy0) - print('co-occuring 1 accuracy=',accuracy1) - print('co-occuring 2 accuracy=',accuracy2) - print('co-occuring 3 accuracy=',accuracy3) - - + accuracy3 = testNN(net, test_loader) + print('default accuracy=', accuracy0) + print('co-occuring 1 accuracy=', accuracy1) + print('co-occuring 2 accuracy=', accuracy2) + print('co-occuring 3 accuracy=', accuracy3) + + else: print('build pretrain model first') criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.1) - net=net.to(device) + net = net.to(device) for epoch in range(10): running_loss = 0.0 for i, data in enumerate(train_loader, 0): inputs, labels = data - inputs=inputs.to(device) - labels=labels.to(device) + inputs = inputs.to(device) + labels = labels.to(device) optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() - print(f"Epoch {epoch+1}: loss = {running_loss / len(train_loader)}") - net=net.to('cpu') + print(f"Epoch {epoch + 1}: loss = {running_loss / len(train_loader)}") + net = net.to('cpu') # Save the pre-trained model torch.save(net.state_dict(), 'pretrained_model.pt') - - - # Evaluate if __name__ == '__main__': - main() \ No newline at end of file + main() diff --git a/commit.sh b/commit.sh index e231f3ca..19788286 100755 --- a/commit.sh +++ b/commit.sh @@ -1,4 +1,4 @@ -BRANCH=E2E +BRANCH=SYSTEST git init git checkout -b $BRANCH git add . diff --git a/commit_info b/commit_info index 41243073..c7a0ca69 100644 --- a/commit_info +++ b/commit_info @@ -1,3 +1,3 @@ -1. fix readme typo of troch install -2. add an experimental E2E machine learning example at benchmark/torchscripts/E2E_Minsit.py +1. add examples of system test +2. fix multi threading bugs on some machines (e.g.., the aarach64), force a single tread now by torch::set_num_threads(1); diff --git a/include/AMMBench.h b/include/AMMBench.h index 8a50aefe..4b39c821 100755 --- a/include/AMMBench.h +++ b/include/AMMBench.h @@ -34,6 +34,11 @@ * - find any .python as an example * - copy and modify it and generate the *pt, please make it under hump style of naming * - the system will then support it by using the name of your pt. + * @section subsec_edit_test How to add a single point test + * - copy your config file to test/scripts, and your pt file to test/torchscripts + * - follow and copy the SketchTest.cpp to create your own, say A.cpp + * - register A.cpp to test/CMakeLists.txt, please follow how we deal with the SketchTest.cpp + * - assuming you have made A.cpp into a_test, append ./a_test "--success" to the last row of .github/workflows/cmake.yml */ /** * @@ -75,6 +80,7 @@ #include #include #include +#include /** * @} */ diff --git a/src/Utils/IntelliLog.cpp b/src/Utils/IntelliLog.cpp index 9448f735..54d7ce7b 100755 --- a/src/Utils/IntelliLog.cpp +++ b/src/Utils/IntelliLog.cpp @@ -22,11 +22,12 @@ void INTELLI::IntelliLog::log(std::string level, std::string_view message, const //str+= static_cast(level); str += ":"; str += source.file_name(); + str += ":"; + str += to_string(source.line()); str += +"|"; str += +source.function_name(); str += +"|"; - str += to_string(source.line()); - str += "|:"; + str += message; cout << str + "\n"; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 967a5020..05e063ee 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -4,17 +4,28 @@ set(CMAKE_CXX_FLAGS "-std=c++20 -Wall -Werror=return-type -Werror=unused-variable -Werror=unused-parameter") enable_testing() add_executable(cpp_test SystemTest/SimpleTest.cpp) +add_executable(sketch_test SystemTest/SketchTest.cpp) message(STATUS " Libraries: ${LIBRARIES}") target_link_libraries(cpp_test IntelliStream ) +target_link_libraries(sketch_test + IntelliStream + ) # avoid undefined reference to "main" in test.cpp add_test( NAME catch_test COMMAND $ --success ) +add_test( + NAME sketch_test + COMMAND $ --success +) file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/torchscripts + DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) + +file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/scripts DESTINATION ${CMAKE_CURRENT_BINARY_DIR}) \ No newline at end of file diff --git a/test/SystemTest/SketchTest.cpp b/test/SystemTest/SketchTest.cpp new file mode 100644 index 00000000..408dde15 --- /dev/null +++ b/test/SystemTest/SketchTest.cpp @@ -0,0 +1,56 @@ +#include + +#define CATCH_CONFIG_MAIN +#include "catch.hpp" +#include +using namespace std; +using namespace INTELLI; +using namespace torch; +void runSingleThreadTest(std::string configName) { + ConfigMapPtr cfg = newConfigMap(); + cfg->fromFile(configName); + AMMBench::MatrixLoaderTable mLoaderTable; + uint64_t sketchDimension; + sketchDimension = cfg->tryU64("sketchDimension", 50, true); + uint64_t coreBind = cfg->tryU64("coreBind", 0, true); + UtilityFunctions::bind2Core((int) coreBind); + torch::set_num_threads(1); + std::string ptFile = cfg->tryString("ptFile", "torchscripts/FDAMM.pt", true); + + //uint64_t customResultName = cfg->tryU64("customResultName", 0, true); + INTELLI_INFO("Place me at core" + to_string(coreBind)); + INTELLI_INFO( + "with sketch" + to_string(sketchDimension)); + torch::jit::script::Module module; + INTELLI_INFO("Try pt file " + ptFile); + module = torch::jit::load(ptFile); + std::string matrixLoaderTag = cfg->tryString("matrixLoaderTag", "random", true); + auto matLoaderPtr = mLoaderTable.findMatrixLoader(matrixLoaderTag); + assert(matLoaderPtr); + matLoaderPtr->setConfig(cfg); + auto A = matLoaderPtr->getA(); + auto B = matLoaderPtr->getB(); + /*torch::manual_seed(114514); +//555 +auto A = torch::rand({(long) aRow, (long) aCol}); +auto B = torch::rand({(long) aCol, (long) bCol});*/ + INTELLI_INFO("Generation done, conducting..."); + ThreadPerf pef((int) coreBind); + pef.setPerfList(); + pef.start(); + auto C =module.forward({A, B, (long) sketchDimension}).toTensor(); + pef.end(); + std::string ruName = "default"; + + auto resultCsv = pef.resultToConfigMap(); + resultCsv->toFile(ruName + ".csv"); + INTELLI_INFO("Done. here is result"); + std::cout << resultCsv->toString() << endl; +} +TEST_CASE("Test the counter sketch", "[short]") +{ + int a = 0; + runSingleThreadTest("scripts/config_counterSketch.csv"); + // place your test here + REQUIRE(a == 0); +} \ No newline at end of file diff --git a/test/scripts/config_counterSketch.csv b/test/scripts/config_counterSketch.csv new file mode 100644 index 00000000..8536ee12 --- /dev/null +++ b/test/scripts/config_counterSketch.csv @@ -0,0 +1,6 @@ +key,value,type +aRow,100,U64 +aCol,1000,U64 +bCol,500,U64 +sketchDimension,25,U64 +ptFile,torchscripts/CountSketch.pt,String \ No newline at end of file diff --git a/test/torchscripts/CountSketch.pt b/test/torchscripts/CountSketch.pt new file mode 100644 index 00000000..71459484 Binary files /dev/null and b/test/torchscripts/CountSketch.pt differ diff --git a/test/torchscripts/CountSketch.py b/test/torchscripts/CountSketch.py new file mode 100644 index 00000000..fc890d98 --- /dev/null +++ b/test/torchscripts/CountSketch.py @@ -0,0 +1,55 @@ +import torch +import time +import os +import math + + +@torch.jit.script +def CountSketch(A: torch.Tensor, B: torch.Tensor, s: int): + m1, n = A.shape + n, m2 = B.shape + # initialize sketch matrices + Ca = torch.zeros((m1, s)) + Cb = torch.zeros((s, m2)) + + L = torch.randint(s, (n,)) + G = torch.randint(2, (n,)) + + # modify the random column with random sign + for i in range(0, n): + if G[i] == 1: + Ca[:, L[i]] += A[:, i] + Cb[L[i], :] += B[i, :] + else: + Ca[:, L[i]] -= A[:, i] + Cb[L[i], :] -= B[i, :] + + return torch.matmul(Ca, Cb) + + +def main(): + width = 1000 + A = torch.rand(10000, width) + B = torch.rand(width, 5000) + + t = time.time() + + aResult = CountSketch(A, B, 500) + print("approximate: " + str(time.time() - t) + "s") + + print(aResult) + + # exact result + t = time.time() + eResult = torch.matmul(A, B) + print("\nExact: " + str(time.time() - t) + "s") + + print(eResult) + + print("\nerror: " + str(torch.norm(aResult - eResult, p='fro').item())) + + CountSketch_script = CountSketch.save("CountSketch.pt") + + +if __name__ == '__main__': + main()