├── .clang-format ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── auto ├── CMakeLists.txt ├── concat.sh ├── generated_main.cu ├── livejournal_p1.cu ├── livejournal_p1_main.cu ├── livejournal_p2.cu ├── livejournal_p2_main.cu ├── livejournal_p3.cu ├── livejournal_p3_main.cu ├── livejournal_p4.cu ├── livejournal_p4_main.cu ├── livejournal_p5.cu ├── livejournal_p5_main.cu ├── livejournal_p6.cu ├── livejournal_p6_main.cu ├── mico_p1.cu ├── mico_p1_main.cu ├── mico_p2.cu ├── mico_p2_main.cu ├── mico_p3.cu ├── mico_p3_main.cu ├── mico_p4.cu ├── mico_p4_main.cu ├── mico_p5.cu ├── mico_p5_main.cu ├── mico_p6.cu ├── mico_p6_main.cu ├── orkut_p1.cu ├── orkut_p1_main.cu ├── orkut_p2.cu ├── orkut_p2_main.cu ├── orkut_p3.cu ├── orkut_p3_main.cu ├── orkut_p4.cu ├── orkut_p4_main.cu ├── orkut_p5.cu ├── orkut_p5_main.cu ├── orkut_p6.cu ├── orkut_p6_main.cu ├── patents_p1.cu ├── patents_p1_main.cu ├── patents_p2.cu ├── patents_p2_main.cu ├── patents_p3.cu ├── patents_p3_main.cu ├── patents_p4.cu ├── patents_p4_main.cu ├── patents_p5.cu ├── patents_p5_main.cu ├── patents_p6.cu └── patents_p6_main.cu ├── code_gen ├── CMakeLists.txt └── final_generator.cu ├── compile_flags.txt ├── dataset ├── mico.adj └── wiki-vote.g ├── env.sh ├── gpu ├── CMakeLists.txt ├── component │ ├── gpu_bitvector.cuh │ ├── gpu_const.cuh │ ├── gpu_device_context.cuh │ ├── gpu_device_detect.cuh │ ├── gpu_schedule.cuh │ ├── gpu_vertex_set.cuh │ └── utils.cuh ├── fsm_mixed.cu ├── function │ └── pattern_matching.cuh ├── gpu_clique.cu ├── gpu_fsm.cu ├── gpu_fsm_omp.cu ├── gpu_graph.cu ├── gpu_graph_mpi.cu ├── gpu_graph_static_task.cu ├── gpu_graph_unimem.cu ├── gpu_kclique.cu ├── gpu_mc.cu ├── gpu_new_fsm.cu ├── gpu_new_str.cu ├── gpu_test.cuh ├── mc3.cu └── src │ ├── gpu_pattern_matching.cuh │ ├── gpu_pattern_matching_multidevices.cuh │ └── gpu_pattern_matching_static_task.cuh ├── include ├── common.h ├── dataloader.h ├── disjoint_set_union.h ├── graph.h ├── graphmpi.h ├── labeled_graph.h ├── motif_generator.h ├── pattern.h ├── prefix.h ├── schedule.h ├── schedule_IEP.h ├── set_operation.hpp ├── timeinterval.h ├── types.h └── vertex_set.h ├── reproduce ├── clique_counting.py ├── frequent_subgraph_mining.py ├── gsi_cuts.py ├── motif_counting.py ├── pattern_matching.py ├── scalability.py ├── settings.py └── utils.py ├── scripts ├── analyze.py ├── check.py ├── fsm_test.py ├── gen_code.py ├── generate.py ├── run.py ├── run_generated_code.py ├── runprof.sh ├── runtest.sh ├── small_graph_check.py └── txt2adj.py ├── spack-env.sh ├── src ├── CMakeLists.txt ├── clique_test.cpp ├── common.cpp ├── dataloader.cpp ├── disjoint_set_union.cpp ├── fsm_test.cpp ├── fsm_vertex_test.cpp ├── graph.cpp ├── graphmpi.cpp ├── in_exclusion_performance_test.cpp ├── labeled_graph.cpp ├── motif_counting_test.cpp ├── motif_generator.cpp ├── pattern.cpp ├── performance_compare_test.cpp ├── pm_test.cpp ├── prefix.cpp ├── restricts_printer.cpp ├── run_brute_force_tc.cpp ├── run_general_tc.cpp ├── schedule.cpp ├── schedule_IEP.cpp ├── schedule_printer.cpp ├── set_operation.cpp └── vertex_set.cpp ├── test ├── CMakeLists.txt ├── gpu_pattern_matching_test.cu ├── gpu_sample_test.cu ├── gtest_main.cpp ├── pattern_matching_test.cpp ├── performance_compare_test.cpp ├── performance_modeling_test.cpp ├── restricts_compare_test.cpp ├── restricts_generation_test.cpp ├── schedule_compare_test.cpp └── schedule_test.cpp └── tianhe ├── CMakeLists.txt ├── all_restricts_test.cpp ├── all_schedule_test.cpp ├── baseline_test.cpp ├── house_twitter_test.cpp ├── in_exclusion_optimize_test.cpp ├── mc_ref.cc ├── our_schedule_our_restricts_test.cpp ├── performance_test.cpp ├── restricts_compare_test.cpp ├── schedule_restricts_test.cpp ├── schedule_restricts_test_old.cpp ├── schedules_our_generator_test.cpp ├── schedules_test.cpp ├── sigmod2020_test.cpp └── triangle_test.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | # BasedOnStyle: LLVM 4 | AccessModifierOffset: -2 5 | AlignAfterOpenBracket: Align 6 | AlignConsecutiveMacros: false 7 | AlignConsecutiveAssignments: false 8 | AlignConsecutiveBitFields: false 9 | AlignConsecutiveDeclarations: false 10 | AlignEscapedNewlines: Right 11 | AlignOperands: Align 12 | AlignTrailingComments: true 13 | AllowAllArgumentsOnNextLine: true 14 | AllowAllConstructorInitializersOnNextLine: true 15 | AllowAllParametersOfDeclarationOnNextLine: true 16 | AllowShortEnumsOnASingleLine: true 17 | AllowShortBlocksOnASingleLine: Never 18 | AllowShortCaseLabelsOnASingleLine: false 19 | AllowShortFunctionsOnASingleLine: All 20 | AllowShortLambdasOnASingleLine: All 21 | AllowShortIfStatementsOnASingleLine: Never 22 | AllowShortLoopsOnASingleLine: false 23 | AlwaysBreakAfterDefinitionReturnType: None 24 | AlwaysBreakAfterReturnType: None 25 | AlwaysBreakBeforeMultilineStrings: false 26 | AlwaysBreakTemplateDeclarations: Yes 27 | BinPackArguments: true 28 | BinPackParameters: true 29 | BraceWrapping: 30 | AfterCaseLabel: false 31 | AfterClass: false 32 | AfterControlStatement: Never 33 | AfterEnum: false 34 | AfterFunction: false 35 | AfterNamespace: false 36 | AfterObjCDeclaration: false 37 | AfterStruct: false 38 | AfterUnion: false 39 | AfterExternBlock: false 40 | BeforeCatch: false 41 | BeforeElse: false 42 | BeforeLambdaBody: false 43 | BeforeWhile: false 44 | IndentBraces: false 45 | SplitEmptyFunction: true 46 | SplitEmptyRecord: true 47 | SplitEmptyNamespace: true 48 | BreakBeforeBinaryOperators: None 49 | BreakBeforeBraces: Attach 50 | BreakBeforeInheritanceComma: false 51 | BreakInheritanceList: BeforeColon 52 | BreakBeforeTernaryOperators: true 53 | BreakConstructorInitializersBeforeComma: false 54 | BreakConstructorInitializers: BeforeColon 55 | BreakAfterJavaFieldAnnotations: false 56 | BreakStringLiterals: true 57 | ColumnLimit: 150 58 | CommentPragmas: '^ IWYU pragma:' 59 | CompactNamespaces: false 60 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 61 | ConstructorInitializerIndentWidth: 4 62 | ContinuationIndentWidth: 4 63 | Cpp11BracedListStyle: true 64 | DeriveLineEnding: true 65 | DerivePointerAlignment: false 66 | DisableFormat: false 67 | ExperimentalAutoDetectBinPacking: false 68 | FixNamespaceComments: true 69 | ForEachMacros: 70 | - foreach 71 | - Q_FOREACH 72 | - BOOST_FOREACH 73 | IncludeBlocks: Preserve 74 | IncludeCategories: 75 | - Regex: '^"(llvm|llvm-c|clang|clang-c)/' 76 | Priority: 2 77 | SortPriority: 0 78 | - Regex: '^(<|"(gtest|gmock|isl|json)/)' 79 | Priority: 3 80 | SortPriority: 0 81 | - Regex: '.*' 82 | Priority: 1 83 | SortPriority: 0 84 | IncludeIsMainRegex: '(Test)?$' 85 | IncludeIsMainSourceRegex: '' 86 | IndentCaseLabels: false 87 | IndentCaseBlocks: false 88 | IndentGotoLabels: true 89 | IndentPPDirectives: None 90 | IndentExternBlock: AfterExternBlock 91 | IndentWidth: 4 92 | IndentWrappedFunctionNames: false 93 | InsertTrailingCommas: None 94 | JavaScriptQuotes: Leave 95 | JavaScriptWrapImports: true 96 | KeepEmptyLinesAtTheStartOfBlocks: true 97 | MacroBlockBegin: '' 98 | MacroBlockEnd: '' 99 | MaxEmptyLinesToKeep: 1 100 | NamespaceIndentation: None 101 | ObjCBinPackProtocolList: Auto 102 | ObjCBlockIndentWidth: 2 103 | ObjCBreakBeforeNestedBlockParam: true 104 | ObjCSpaceAfterProperty: false 105 | ObjCSpaceBeforeProtocolList: true 106 | PenaltyBreakAssignment: 2 107 | PenaltyBreakBeforeFirstCallParameter: 19 108 | PenaltyBreakComment: 300 109 | PenaltyBreakFirstLessLess: 120 110 | PenaltyBreakString: 1000 111 | PenaltyBreakTemplateDeclaration: 10 112 | PenaltyExcessCharacter: 1000000 113 | PenaltyReturnTypeOnItsOwnLine: 60 114 | PointerAlignment: Right 115 | ReflowComments: true 116 | SortIncludes: true 117 | SortUsingDeclarations: true 118 | SpaceAfterCStyleCast: false 119 | SpaceAfterLogicalNot: false 120 | SpaceAfterTemplateKeyword: true 121 | SpaceBeforeAssignmentOperators: true 122 | SpaceBeforeCpp11BracedList: false 123 | SpaceBeforeCtorInitializerColon: true 124 | SpaceBeforeInheritanceColon: true 125 | SpaceBeforeParens: ControlStatements 126 | SpaceBeforeRangeBasedForLoopColon: true 127 | SpaceInEmptyBlock: false 128 | SpaceInEmptyParentheses: false 129 | SpacesBeforeTrailingComments: 1 130 | SpacesInAngles: false 131 | SpacesInConditionalStatement: false 132 | SpacesInContainerLiterals: true 133 | SpacesInCStyleCastParentheses: false 134 | SpacesInParentheses: false 135 | SpacesInSquareBrackets: false 136 | SpaceBeforeSquareBrackets: false 137 | Standard: Latest 138 | StatementMacros: 139 | - Q_UNUSED 140 | - QT_REQUIRE_VERSION 141 | TabWidth: 4 142 | UseCRLF: false 143 | UseTab: Never 144 | WhitespaceSensitiveMacros: 145 | - STRINGIZE 146 | - PP_STRINGIZE 147 | - BOOST_PP_STRINGIZE 148 | ... 149 | 150 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | .vscode/ 3 | log/ 4 | reproduce_log/ 5 | **/__pycache__/ -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "modules/googletest"] 2 | path = modules/googletest 3 | url = https://github.com/google/googletest.git 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | CMAKE_MINIMUM_REQUIRED(VERSION 3.12) 2 | PROJECT(GraphMining LANGUAGES CXX CUDA) 3 | INCLUDE_DIRECTORIES(include) 4 | INCLUDE_DIRECTORIES(gpu) 5 | 6 | SET(CMAKE_BUILD_TYPE RELEASE) 7 | set(CMAKE_CXX_STANDARD 14) 8 | # SET(CMAKE_BUILD_TYPE DEBUG) 9 | SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb -march=native") 10 | SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -march=native") 11 | SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/libs) 12 | SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 13 | 14 | 15 | find_package(OpenMP REQUIRED) 16 | if(OPENMP_FOUND) 17 | message("OPENMP FOUND") 18 | INCLUDE_DIRECTORIES(${OpenMP_INCLUDE_DIRS}) 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}" ) 20 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}" ) 21 | set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${OpenMP_CXX_FLAGS}" ) 22 | set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${OpenMP_CXX_FLAGS}" ) 23 | 24 | set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -maxrregcount=64 -Xcompiler=\"${OpenMP_CXX_FLAGS}\"" ) 25 | set(CMAKE_CUDA_ARCHITECTURES 70) 26 | set(CMAKE_CUDA_FLAGS_RELEASE "${CMAKE_CUDA_FLAGS_RELEASE} -lineinfo" ) 27 | set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -lineinfo --ptxas-options=-v" ) 28 | # set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -lineinfo --ptxas-options=-v" ) 29 | # set(CMAKE_CUDA_FLAGS_DEBUG "${CMAKE_CUDA_FLAGS_DEBUG} -G --ptxas-options=-v" ) 30 | 31 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}" ) 32 | set(CMAKE_SHARE_LINKER_FLAGS "${CMAKE_SHARE_LINKER_FLAGS} ${OpenMP_SHARE_LINKER_FLAGS}" ) 33 | #TARGET_COMPILE_OPTIONS(graph_mining PRIVATE -Wall ${OpenMP_CXX_FLAGS}) 34 | endif() 35 | 36 | 37 | # set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 38 | # add_subdirectory(modules/googletest) 39 | # MESSAGE("ADD GOOGLE TEST") 40 | 41 | find_package(MPI REQUIRED) 42 | if(MPI_FOUND) 43 | SET(CMAKE_CXX_COMPILER mpicxx) 44 | MESSAGE("MPI FOUND") 45 | endif() 46 | 47 | ADD_SUBDIRECTORY(src) 48 | # ADD_SUBDIRECTORY(test) 49 | ADD_SUBDIRECTORY(tianhe) 50 | ADD_SUBDIRECTORY(gpu) 51 | ADD_SUBDIRECTORY(code_gen) 52 | ADD_SUBDIRECTORY(auto) 53 | 54 | MESSAGE("CMAKE_C_FLAGS = " ${CMAKE_C_FLAGS}) 55 | MESSAGE("CMAKE_CXX_FLAGS = " ${CMAKE_CXX_FLAGS}) 56 | MESSAGE("CMAKE_CXX_FLAGS_RELEASE = " ${CMAKE_CXX_FLAGS_RELEASE}) 57 | MESSAGE("CMAKE_CXX_FLAGS_DEBUG = " ${CMAKE_CXX_FLAGS_DEBUG}) 58 | MESSAGE("CMAKE_CUDA_FLAGS = " ${CMAKE_CUDA_FLAGS}) 59 | MESSAGE("CMAKE_CUDA_FLAGS_RELEASE = " ${CMAKE_CUDA_FLAGS_RELEASE}) 60 | MESSAGE("CMAKE_CUDA_FLAGS_DEBUG = " ${CMAKE_CUDA_FLAGS_DEBUG}) 61 | MESSAGE("CMAKE_EXE_LINKER_FLAGS = " ${CMAKE_EXE_LINKER_FLAGS}) 62 | MESSAGE("PROJECT BINARY DIR = " ${PROJECT_BINARY_DIR}) 63 | MESSAGE("INCLUDE DIRECTORIES = " ${CPLUS_INCLUDE_PATH}) 64 | MESSAGE("CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) 65 | MESSAGE("CMAKE_INSTALL_PREFIX = " ${CMAKE_INSTALL_PREFIX}) 66 | MESSAGE("OpenMP_EXE_LINKER_FLAGS = " ${OpenMP_EXE_LINKER_FLAGS}) 67 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 sth1997 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /auto/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | list(APPEND GRAPH "patents" "mico" "livejournal" "orkut") 2 | SET(N 6) 3 | 4 | FOREACH(G IN LISTS GRAPH) 5 | FOREACH(X RANGE 1 ${N}) 6 | ADD_EXECUTABLE(${G}_p${X} ${G}_p${X}_main.cu) 7 | SET_PROPERTY(TARGET ${G}_p${X} PROPERTY CUDA_SEPARABLE_COMPILATION ON) 8 | TARGET_LINK_LIBRARIES(${G}_p${X} graph_mining) 9 | ENDFOREACH() 10 | ENDFOREACH() -------------------------------------------------------------------------------- /auto/concat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | p1="5 0111010011100011100001100" 3 | p2="6 011011101110110101011000110000101000" 4 | p3="6 011111101000110111101010101101101010" 5 | p4="6 011110101101110000110000100001010010" 6 | p5="7 0111111101111111011101110100111100011100001100000" 7 | p6="7 0111111101111111011001110100111100011000001100000" 8 | 9 | for name in "patents" "mico" "livejournal" "orkut" 10 | do 11 | for ((i=1; i<=6; i++)) 12 | do 13 | cat generated_main.cu > ${name}_p${i}_main.cu 14 | cat ${name}_p${i}.cu >> ${name}_p${i}_main.cu 15 | done 16 | done -------------------------------------------------------------------------------- /auto/generated_main.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | #include "component/utils.cuh" 21 | #include "component/gpu_device_context.cuh" 22 | #include "component/gpu_device_detect.cuh" 23 | #include "src/gpu_pattern_matching.cuh" 24 | #include "timeinterval.h" 25 | 26 | 27 | __global__ void gpu_pattern_matching_generated(e_index_t edge_num, uint32_t buffer_size, PatternMatchingDeviceContext *context); 28 | 29 | 30 | TimeInterval allTime; 31 | TimeInterval tmpTime; 32 | 33 | void pattern_matching(Graph *g, const Schedule_IEP &schedule_iep) { 34 | tmpTime.check(); 35 | PatternMatchingDeviceContext *context; 36 | gpuErrchk(cudaMallocManaged((void **)&context, sizeof(PatternMatchingDeviceContext))); 37 | context->init(g, schedule_iep); 38 | 39 | uint32_t buffer_size = VertexSet::max_intersection_size; 40 | int max_active_blocks_per_sm; 41 | cudaOccupancyMaxActiveBlocksPerMultiprocessor(&max_active_blocks_per_sm, gpu_pattern_matching, THREADS_PER_BLOCK, context->block_shmem_size); 42 | fprintf(stderr, "max number of active warps per SM: %d\n", max_active_blocks_per_sm * WARPS_PER_BLOCK); 43 | 44 | tmpTime.print("Prepare time cost"); 45 | tmpTime.check(); 46 | 47 | unsigned long long sum = 0; 48 | 49 | gpu_pattern_matching_generated<<block_shmem_size>>>(g->e_cnt, buffer_size, context); 50 | 51 | gpuErrchk(cudaPeekAtLastError()); 52 | gpuErrchk(cudaDeviceSynchronize()); 53 | gpuErrchk(cudaMemcpy(&sum, context->dev_sum, sizeof(sum), cudaMemcpyDeviceToHost)); 54 | 55 | sum /= schedule_iep.get_in_exclusion_optimize_redundancy(); 56 | 57 | printf("Pattern count: %llu\n", sum); 58 | tmpTime.print("Counting time cost"); 59 | 60 | context->destroy(); 61 | gpuErrchk(cudaFree(context)); 62 | } 63 | 64 | int main(int argc, char *argv[]) { 65 | get_device_information(); 66 | Graph *g; 67 | DataLoader D; 68 | 69 | if (argc < 2) { 70 | fprintf(stderr, "Usage: %s graph_file pattern_size pattern_string\n", argv[0]); 71 | return 1; 72 | } 73 | 74 | using std::chrono::system_clock; 75 | auto t1 = system_clock::now(); 76 | 77 | bool ok = D.fast_load(g, argv[1]); 78 | if (!ok) { 79 | fprintf(stderr, "data load failure :-(\n"); 80 | return 0; 81 | } 82 | 83 | auto t2 = system_clock::now(); 84 | auto load_time = std::chrono::duration_cast(t2 - t1); 85 | fprintf(stderr, "Load data success! time: %g seconds\n", load_time.count() / 1.0e6); 86 | 87 | allTime.check(); 88 | 89 | int pattern_size = atoi(argv[2]); 90 | const char *pattern_str = argv[3]; 91 | 92 | Pattern p(pattern_size, pattern_str); 93 | 94 | printf("pattern = "); 95 | p.print(); 96 | 97 | fprintf(stderr, "Max intersection size %d\n", VertexSet::max_intersection_size); 98 | 99 | bool is_pattern_valid; 100 | Schedule_IEP schedule_iep(p, is_pattern_valid, 1, 1, true, g->v_cnt, g->e_cnt, g->tri_cnt); 101 | if (!is_pattern_valid) { 102 | fprintf(stderr, "pattern is invalid!\n"); 103 | return 1; 104 | } 105 | 106 | pattern_matching(g, schedule_iep); 107 | 108 | allTime.print("Total time cost"); 109 | return 0; 110 | } 111 | -------------------------------------------------------------------------------- /auto/livejournal_p3.cu: -------------------------------------------------------------------------------- 1 | __global__ void gpu_pattern_matching_generated(e_index_t edge_num, uint32_t buffer_size, PatternMatchingDeviceContext *context) { 2 | __shared__ e_index_t block_edge_idx[WARPS_PER_BLOCK]; 3 | extern __shared__ GPUVertexSet block_vertex_set[]; 4 | GPUSchedule *schedule = context->dev_schedule; 5 | uint32_t *tmp = context->dev_tmp; 6 | uint32_t *edge = (uint32_t *)context->dev_edge; 7 | e_index_t *vertex = context->dev_vertex; 8 | uint32_t *edge_from = (uint32_t *)context->dev_edge_from; 9 | int wid = threadIdx.x / THREADS_PER_WARP, lid = threadIdx.x % THREADS_PER_WARP, global_wid = blockIdx.x * WARPS_PER_BLOCK + wid; 10 | e_index_t &edge_idx = block_edge_idx[wid]; 11 | GPUVertexSet *vertex_set = block_vertex_set + wid * 5; 12 | if (lid == 0) { 13 | edge_idx = 0; 14 | uint32_t offset = buffer_size * global_wid * 5; 15 | for (int i = 0; i < 5; ++i) { 16 | vertex_set[i].set_data_ptr(tmp + offset); 17 | offset += buffer_size; 18 | } 19 | } 20 | GPUVertexSet& subtraction_set = vertex_set[3]; 21 | __threadfence_block(); 22 | uint32_t v0, v1; 23 | e_index_t l, r; 24 | unsigned long long sum = 0; 25 | while (true) { 26 | if (lid == 0) { 27 | edge_idx = atomicAdd(context->dev_cur_edge, 1); 28 | unsigned int i = edge_idx; 29 | if (i < edge_num) { 30 | subtraction_set.init(); 31 | subtraction_set.push_back(edge_from[i]); 32 | subtraction_set.push_back(edge[i]); 33 | } 34 | } 35 | __threadfence_block(); 36 | e_index_t i = edge_idx; 37 | if(i >= edge_num) break; 38 | v0 = edge_from[i]; 39 | v1 = edge[i]; 40 | get_edge_index(v0, l, r); 41 | if (threadIdx.x % THREADS_PER_WARP == 0) 42 | vertex_set[0].init(r - l, &edge[l]); 43 | __threadfence_block(); 44 | if(v0 <= v1) continue; 45 | get_edge_index(v1, l, r); 46 | GPUVertexSet* tmp_vset; 47 | intersection2(vertex_set[1].get_data_ptr(), vertex_set[0].get_data_ptr(), &edge[l], vertex_set[0].get_size(), r - l, &vertex_set[1].size); 48 | if (vertex_set[1].get_size() == 0) continue; 49 | extern __shared__ char ans_array[]; 50 | int* ans = ((int*) (ans_array + 576)) + 2 * (threadIdx.x / THREADS_PER_WARP); 51 | int loop_size_depth2 = vertex_set[1].get_size(); 52 | if( loop_size_depth2 <= 0) continue; 53 | uint32_t* loop_data_ptr_depth2 = vertex_set[1].get_data_ptr(); 54 | uint32_t min_vertex_depth2 = 0xffffffff; 55 | for(int i_depth2 = 0; i_depth2 < loop_size_depth2; ++i_depth2) { 56 | uint32_t v_depth2 = loop_data_ptr_depth2[i_depth2]; 57 | if(subtraction_set.has_data(v_depth2)) continue; 58 | unsigned int l_depth2, r_depth2; 59 | get_edge_index(v_depth2, l_depth2, r_depth2); 60 | { 61 | tmp_vset = &vertex_set[2]; 62 | if (threadIdx.x % THREADS_PER_WARP == 0) 63 | tmp_vset->init(r_depth2 - l_depth2, &edge[l_depth2]); 64 | __threadfence_block(); 65 | if (r_depth2 - l_depth2 > vertex_set[1].get_size()) 66 | tmp_vset->size -= unordered_subtraction_size(*tmp_vset, vertex_set[1], -1); 67 | else 68 | tmp_vset->size = vertex_set[1].get_size() - unordered_subtraction_size(vertex_set[1], *tmp_vset, -1); 69 | } 70 | if (vertex_set[2].get_size() == 0) continue; 71 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.push_back(v_depth2); 72 | __threadfence_block(); 73 | ans[0] = vertex_set[1].get_size() - 1; 74 | ans[1] = vertex_set[2].get_size() - 0; 75 | long long val; 76 | val = ans[0]; 77 | val = val * ans[1]; 78 | val = val * ans[1]; 79 | sum += val * 1; 80 | val = ans[1]; 81 | val = val * ans[1]; 82 | sum += val * -1; 83 | val = ans[0]; 84 | val = val * ans[1]; 85 | sum += val * -1; 86 | val = ans[1]; 87 | val = val * ans[1]; 88 | sum += val * -1; 89 | val = ans[1]; 90 | sum += val * 2; 91 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.pop_back(); 92 | __threadfence_block(); 93 | } 94 | } 95 | if (lid == 0) atomicAdd(context->dev_sum, sum); 96 | } 97 | -------------------------------------------------------------------------------- /auto/mico_p1.cu: -------------------------------------------------------------------------------- 1 | __global__ void gpu_pattern_matching_generated(e_index_t edge_num, uint32_t buffer_size, PatternMatchingDeviceContext *context) { 2 | __shared__ e_index_t block_edge_idx[WARPS_PER_BLOCK]; 3 | extern __shared__ GPUVertexSet block_vertex_set[]; 4 | GPUSchedule *schedule = context->dev_schedule; 5 | uint32_t *tmp = context->dev_tmp; 6 | uint32_t *edge = (uint32_t *)context->dev_edge; 7 | e_index_t *vertex = context->dev_vertex; 8 | uint32_t *edge_from = (uint32_t *)context->dev_edge_from; 9 | int wid = threadIdx.x / THREADS_PER_WARP, lid = threadIdx.x % THREADS_PER_WARP, global_wid = blockIdx.x * WARPS_PER_BLOCK + wid; 10 | e_index_t &edge_idx = block_edge_idx[wid]; 11 | GPUVertexSet *vertex_set = block_vertex_set + wid * 7; 12 | if (lid == 0) { 13 | edge_idx = 0; 14 | uint32_t offset = buffer_size * global_wid * 7; 15 | for (int i = 0; i < 7; ++i) { 16 | vertex_set[i].set_data_ptr(tmp + offset); 17 | offset += buffer_size; 18 | } 19 | } 20 | GPUVertexSet& subtraction_set = vertex_set[5]; 21 | __threadfence_block(); 22 | uint32_t v0, v1; 23 | e_index_t l, r; 24 | unsigned long long sum = 0; 25 | while (true) { 26 | if (lid == 0) { 27 | edge_idx = atomicAdd(context->dev_cur_edge, 1); 28 | unsigned int i = edge_idx; 29 | if (i < edge_num) { 30 | subtraction_set.init(); 31 | subtraction_set.push_back(edge_from[i]); 32 | subtraction_set.push_back(edge[i]); 33 | } 34 | } 35 | __threadfence_block(); 36 | e_index_t i = edge_idx; 37 | if(i >= edge_num) break; 38 | v0 = edge_from[i]; 39 | v1 = edge[i]; 40 | get_edge_index(v0, l, r); 41 | if (threadIdx.x % THREADS_PER_WARP == 0) 42 | vertex_set[0].init(r - l, &edge[l]); 43 | __threadfence_block(); 44 | if(v0 <= v1) continue; 45 | get_edge_index(v1, l, r); 46 | GPUVertexSet* tmp_vset; 47 | intersection2(vertex_set[1].get_data_ptr(), vertex_set[0].get_data_ptr(), &edge[l], vertex_set[0].get_size(), r - l, &vertex_set[1].size); 48 | if (vertex_set[1].get_size() == 0) continue; 49 | if (threadIdx.x % THREADS_PER_WARP == 0) 50 | vertex_set[2].init(r - l, &edge[l]); 51 | __threadfence_block(); 52 | if (vertex_set[2].get_size() == 0) continue; 53 | extern __shared__ char ans_array[]; 54 | int* ans = ((int*) (ans_array + 640)) + 3 * (threadIdx.x / THREADS_PER_WARP); 55 | int loop_size_depth2 = vertex_set[0].get_size(); 56 | if( loop_size_depth2 <= 0) continue; 57 | uint32_t* loop_data_ptr_depth2 = vertex_set[0].get_data_ptr(); 58 | uint32_t min_vertex_depth2 = 0xffffffff; 59 | for(int i_depth2 = 0; i_depth2 < loop_size_depth2; ++i_depth2) { 60 | uint32_t v_depth2 = loop_data_ptr_depth2[i_depth2]; 61 | if(subtraction_set.has_data(v_depth2)) continue; 62 | unsigned int l_depth2, r_depth2; 63 | get_edge_index(v_depth2, l_depth2, r_depth2); 64 | { 65 | tmp_vset = &vertex_set[3]; 66 | if (threadIdx.x % THREADS_PER_WARP == 0) 67 | tmp_vset->init(r_depth2 - l_depth2, &edge[l_depth2]); 68 | __threadfence_block(); 69 | if (r_depth2 - l_depth2 > vertex_set[2].get_size()) 70 | tmp_vset->size -= unordered_subtraction_size(*tmp_vset, vertex_set[2], -1); 71 | else 72 | tmp_vset->size = vertex_set[2].get_size() - unordered_subtraction_size(vertex_set[2], *tmp_vset, -1); 73 | } 74 | if (vertex_set[3].get_size() == 1) continue; 75 | { 76 | tmp_vset = &vertex_set[4]; 77 | if (threadIdx.x % THREADS_PER_WARP == 0) 78 | tmp_vset->init(r_depth2 - l_depth2, &edge[l_depth2]); 79 | __threadfence_block(); 80 | if (r_depth2 - l_depth2 > vertex_set[1].get_size()) 81 | tmp_vset->size -= unordered_subtraction_size(*tmp_vset, vertex_set[1], -1); 82 | else 83 | tmp_vset->size = vertex_set[1].get_size() - unordered_subtraction_size(vertex_set[1], *tmp_vset, -1); 84 | } 85 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.push_back(v_depth2); 86 | __threadfence_block(); 87 | ans[0] = unordered_subtraction_size(vertex_set[1], subtraction_set); 88 | ans[1] = vertex_set[3].get_size() - 1; 89 | ans[2] = vertex_set[4].get_size() - 0; 90 | long long val; 91 | val = ans[0]; 92 | val = val * ans[1]; 93 | sum += val * 1; 94 | val = ans[2]; 95 | sum += val * -1; 96 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.pop_back(); 97 | __threadfence_block(); 98 | } 99 | } 100 | if (lid == 0) atomicAdd(context->dev_sum, sum); 101 | } 102 | -------------------------------------------------------------------------------- /auto/mico_p3.cu: -------------------------------------------------------------------------------- 1 | __global__ void gpu_pattern_matching_generated(e_index_t edge_num, uint32_t buffer_size, PatternMatchingDeviceContext *context) { 2 | __shared__ e_index_t block_edge_idx[WARPS_PER_BLOCK]; 3 | extern __shared__ GPUVertexSet block_vertex_set[]; 4 | GPUSchedule *schedule = context->dev_schedule; 5 | uint32_t *tmp = context->dev_tmp; 6 | uint32_t *edge = (uint32_t *)context->dev_edge; 7 | e_index_t *vertex = context->dev_vertex; 8 | uint32_t *edge_from = (uint32_t *)context->dev_edge_from; 9 | int wid = threadIdx.x / THREADS_PER_WARP, lid = threadIdx.x % THREADS_PER_WARP, global_wid = blockIdx.x * WARPS_PER_BLOCK + wid; 10 | e_index_t &edge_idx = block_edge_idx[wid]; 11 | GPUVertexSet *vertex_set = block_vertex_set + wid * 5; 12 | if (lid == 0) { 13 | edge_idx = 0; 14 | uint32_t offset = buffer_size * global_wid * 5; 15 | for (int i = 0; i < 5; ++i) { 16 | vertex_set[i].set_data_ptr(tmp + offset); 17 | offset += buffer_size; 18 | } 19 | } 20 | GPUVertexSet& subtraction_set = vertex_set[3]; 21 | __threadfence_block(); 22 | uint32_t v0, v1; 23 | e_index_t l, r; 24 | unsigned long long sum = 0; 25 | while (true) { 26 | if (lid == 0) { 27 | edge_idx = atomicAdd(context->dev_cur_edge, 1); 28 | unsigned int i = edge_idx; 29 | if (i < edge_num) { 30 | subtraction_set.init(); 31 | subtraction_set.push_back(edge_from[i]); 32 | subtraction_set.push_back(edge[i]); 33 | } 34 | } 35 | __threadfence_block(); 36 | e_index_t i = edge_idx; 37 | if(i >= edge_num) break; 38 | v0 = edge_from[i]; 39 | v1 = edge[i]; 40 | get_edge_index(v0, l, r); 41 | if (threadIdx.x % THREADS_PER_WARP == 0) 42 | vertex_set[0].init(r - l, &edge[l]); 43 | __threadfence_block(); 44 | if(v0 <= v1) continue; 45 | get_edge_index(v1, l, r); 46 | GPUVertexSet* tmp_vset; 47 | intersection2(vertex_set[1].get_data_ptr(), vertex_set[0].get_data_ptr(), &edge[l], vertex_set[0].get_size(), r - l, &vertex_set[1].size); 48 | if (vertex_set[1].get_size() == 0) continue; 49 | extern __shared__ char ans_array[]; 50 | int* ans = ((int*) (ans_array + 576)) + 2 * (threadIdx.x / THREADS_PER_WARP); 51 | int loop_size_depth2 = vertex_set[1].get_size(); 52 | if( loop_size_depth2 <= 0) continue; 53 | uint32_t* loop_data_ptr_depth2 = vertex_set[1].get_data_ptr(); 54 | uint32_t min_vertex_depth2 = 0xffffffff; 55 | for(int i_depth2 = 0; i_depth2 < loop_size_depth2; ++i_depth2) { 56 | uint32_t v_depth2 = loop_data_ptr_depth2[i_depth2]; 57 | if(subtraction_set.has_data(v_depth2)) continue; 58 | unsigned int l_depth2, r_depth2; 59 | get_edge_index(v_depth2, l_depth2, r_depth2); 60 | { 61 | tmp_vset = &vertex_set[2]; 62 | if (threadIdx.x % THREADS_PER_WARP == 0) 63 | tmp_vset->init(r_depth2 - l_depth2, &edge[l_depth2]); 64 | __threadfence_block(); 65 | if (r_depth2 - l_depth2 > vertex_set[1].get_size()) 66 | tmp_vset->size -= unordered_subtraction_size(*tmp_vset, vertex_set[1], -1); 67 | else 68 | tmp_vset->size = vertex_set[1].get_size() - unordered_subtraction_size(vertex_set[1], *tmp_vset, -1); 69 | } 70 | if (vertex_set[2].get_size() == 0) continue; 71 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.push_back(v_depth2); 72 | __threadfence_block(); 73 | ans[0] = vertex_set[1].get_size() - 1; 74 | ans[1] = vertex_set[2].get_size() - 0; 75 | long long val; 76 | val = ans[0]; 77 | val = val * ans[1]; 78 | val = val * ans[1]; 79 | sum += val * 1; 80 | val = ans[1]; 81 | val = val * ans[1]; 82 | sum += val * -1; 83 | val = ans[0]; 84 | val = val * ans[1]; 85 | sum += val * -1; 86 | val = ans[1]; 87 | val = val * ans[1]; 88 | sum += val * -1; 89 | val = ans[1]; 90 | sum += val * 2; 91 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.pop_back(); 92 | __threadfence_block(); 93 | } 94 | } 95 | if (lid == 0) atomicAdd(context->dev_sum, sum); 96 | } 97 | -------------------------------------------------------------------------------- /auto/orkut_p1.cu: -------------------------------------------------------------------------------- 1 | __global__ void gpu_pattern_matching_generated(e_index_t edge_num, uint32_t buffer_size, PatternMatchingDeviceContext *context) { 2 | __shared__ e_index_t block_edge_idx[WARPS_PER_BLOCK]; 3 | extern __shared__ GPUVertexSet block_vertex_set[]; 4 | GPUSchedule *schedule = context->dev_schedule; 5 | uint32_t *tmp = context->dev_tmp; 6 | uint32_t *edge = (uint32_t *)context->dev_edge; 7 | e_index_t *vertex = context->dev_vertex; 8 | uint32_t *edge_from = (uint32_t *)context->dev_edge_from; 9 | int wid = threadIdx.x / THREADS_PER_WARP, lid = threadIdx.x % THREADS_PER_WARP, global_wid = blockIdx.x * WARPS_PER_BLOCK + wid; 10 | e_index_t &edge_idx = block_edge_idx[wid]; 11 | GPUVertexSet *vertex_set = block_vertex_set + wid * 7; 12 | if (lid == 0) { 13 | edge_idx = 0; 14 | uint32_t offset = buffer_size * global_wid * 7; 15 | for (int i = 0; i < 7; ++i) { 16 | vertex_set[i].set_data_ptr(tmp + offset); 17 | offset += buffer_size; 18 | } 19 | } 20 | GPUVertexSet& subtraction_set = vertex_set[5]; 21 | __threadfence_block(); 22 | uint32_t v0, v1; 23 | e_index_t l, r; 24 | unsigned long long sum = 0; 25 | while (true) { 26 | if (lid == 0) { 27 | edge_idx = atomicAdd(context->dev_cur_edge, 1); 28 | unsigned int i = edge_idx; 29 | if (i < edge_num) { 30 | subtraction_set.init(); 31 | subtraction_set.push_back(edge_from[i]); 32 | subtraction_set.push_back(edge[i]); 33 | } 34 | } 35 | __threadfence_block(); 36 | e_index_t i = edge_idx; 37 | if(i >= edge_num) break; 38 | v0 = edge_from[i]; 39 | v1 = edge[i]; 40 | get_edge_index(v0, l, r); 41 | if (threadIdx.x % THREADS_PER_WARP == 0) 42 | vertex_set[0].init(r - l, &edge[l]); 43 | __threadfence_block(); 44 | if(v0 <= v1) continue; 45 | get_edge_index(v1, l, r); 46 | GPUVertexSet* tmp_vset; 47 | intersection2(vertex_set[1].get_data_ptr(), vertex_set[0].get_data_ptr(), &edge[l], vertex_set[0].get_size(), r - l, &vertex_set[1].size); 48 | if (vertex_set[1].get_size() == 0) continue; 49 | if (threadIdx.x % THREADS_PER_WARP == 0) 50 | vertex_set[2].init(r - l, &edge[l]); 51 | __threadfence_block(); 52 | if (vertex_set[2].get_size() == 0) continue; 53 | extern __shared__ char ans_array[]; 54 | int* ans = ((int*) (ans_array + 640)) + 3 * (threadIdx.x / THREADS_PER_WARP); 55 | int loop_size_depth2 = vertex_set[0].get_size(); 56 | if( loop_size_depth2 <= 0) continue; 57 | uint32_t* loop_data_ptr_depth2 = vertex_set[0].get_data_ptr(); 58 | uint32_t min_vertex_depth2 = 0xffffffff; 59 | for(int i_depth2 = 0; i_depth2 < loop_size_depth2; ++i_depth2) { 60 | uint32_t v_depth2 = loop_data_ptr_depth2[i_depth2]; 61 | if(subtraction_set.has_data(v_depth2)) continue; 62 | unsigned int l_depth2, r_depth2; 63 | get_edge_index(v_depth2, l_depth2, r_depth2); 64 | { 65 | tmp_vset = &vertex_set[3]; 66 | if (threadIdx.x % THREADS_PER_WARP == 0) 67 | tmp_vset->init(r_depth2 - l_depth2, &edge[l_depth2]); 68 | __threadfence_block(); 69 | if (r_depth2 - l_depth2 > vertex_set[2].get_size()) 70 | tmp_vset->size -= unordered_subtraction_size(*tmp_vset, vertex_set[2], -1); 71 | else 72 | tmp_vset->size = vertex_set[2].get_size() - unordered_subtraction_size(vertex_set[2], *tmp_vset, -1); 73 | } 74 | if (vertex_set[3].get_size() == 1) continue; 75 | { 76 | tmp_vset = &vertex_set[4]; 77 | if (threadIdx.x % THREADS_PER_WARP == 0) 78 | tmp_vset->init(r_depth2 - l_depth2, &edge[l_depth2]); 79 | __threadfence_block(); 80 | if (r_depth2 - l_depth2 > vertex_set[1].get_size()) 81 | tmp_vset->size -= unordered_subtraction_size(*tmp_vset, vertex_set[1], -1); 82 | else 83 | tmp_vset->size = vertex_set[1].get_size() - unordered_subtraction_size(vertex_set[1], *tmp_vset, -1); 84 | } 85 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.push_back(v_depth2); 86 | __threadfence_block(); 87 | ans[0] = unordered_subtraction_size(vertex_set[1], subtraction_set); 88 | ans[1] = vertex_set[3].get_size() - 1; 89 | ans[2] = vertex_set[4].get_size() - 0; 90 | long long val; 91 | val = ans[0]; 92 | val = val * ans[1]; 93 | sum += val * 1; 94 | val = ans[2]; 95 | sum += val * -1; 96 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.pop_back(); 97 | __threadfence_block(); 98 | } 99 | } 100 | if (lid == 0) atomicAdd(context->dev_sum, sum); 101 | } 102 | -------------------------------------------------------------------------------- /auto/orkut_p3.cu: -------------------------------------------------------------------------------- 1 | __global__ void gpu_pattern_matching_generated(e_index_t edge_num, uint32_t buffer_size, PatternMatchingDeviceContext *context) { 2 | __shared__ e_index_t block_edge_idx[WARPS_PER_BLOCK]; 3 | extern __shared__ GPUVertexSet block_vertex_set[]; 4 | GPUSchedule *schedule = context->dev_schedule; 5 | uint32_t *tmp = context->dev_tmp; 6 | uint32_t *edge = (uint32_t *)context->dev_edge; 7 | e_index_t *vertex = context->dev_vertex; 8 | uint32_t *edge_from = (uint32_t *)context->dev_edge_from; 9 | int wid = threadIdx.x / THREADS_PER_WARP, lid = threadIdx.x % THREADS_PER_WARP, global_wid = blockIdx.x * WARPS_PER_BLOCK + wid; 10 | e_index_t &edge_idx = block_edge_idx[wid]; 11 | GPUVertexSet *vertex_set = block_vertex_set + wid * 5; 12 | if (lid == 0) { 13 | edge_idx = 0; 14 | uint32_t offset = buffer_size * global_wid * 5; 15 | for (int i = 0; i < 5; ++i) { 16 | vertex_set[i].set_data_ptr(tmp + offset); 17 | offset += buffer_size; 18 | } 19 | } 20 | GPUVertexSet& subtraction_set = vertex_set[3]; 21 | __threadfence_block(); 22 | uint32_t v0, v1; 23 | e_index_t l, r; 24 | unsigned long long sum = 0; 25 | while (true) { 26 | if (lid == 0) { 27 | edge_idx = atomicAdd(context->dev_cur_edge, 1); 28 | unsigned int i = edge_idx; 29 | if (i < edge_num) { 30 | subtraction_set.init(); 31 | subtraction_set.push_back(edge_from[i]); 32 | subtraction_set.push_back(edge[i]); 33 | } 34 | } 35 | __threadfence_block(); 36 | e_index_t i = edge_idx; 37 | if(i >= edge_num) break; 38 | v0 = edge_from[i]; 39 | v1 = edge[i]; 40 | get_edge_index(v0, l, r); 41 | if (threadIdx.x % THREADS_PER_WARP == 0) 42 | vertex_set[0].init(r - l, &edge[l]); 43 | __threadfence_block(); 44 | if(v0 <= v1) continue; 45 | get_edge_index(v1, l, r); 46 | GPUVertexSet* tmp_vset; 47 | intersection2(vertex_set[1].get_data_ptr(), vertex_set[0].get_data_ptr(), &edge[l], vertex_set[0].get_size(), r - l, &vertex_set[1].size); 48 | if (vertex_set[1].get_size() == 0) continue; 49 | extern __shared__ char ans_array[]; 50 | int* ans = ((int*) (ans_array + 576)) + 2 * (threadIdx.x / THREADS_PER_WARP); 51 | int loop_size_depth2 = vertex_set[1].get_size(); 52 | if( loop_size_depth2 <= 0) continue; 53 | uint32_t* loop_data_ptr_depth2 = vertex_set[1].get_data_ptr(); 54 | uint32_t min_vertex_depth2 = 0xffffffff; 55 | for(int i_depth2 = 0; i_depth2 < loop_size_depth2; ++i_depth2) { 56 | uint32_t v_depth2 = loop_data_ptr_depth2[i_depth2]; 57 | if(subtraction_set.has_data(v_depth2)) continue; 58 | unsigned int l_depth2, r_depth2; 59 | get_edge_index(v_depth2, l_depth2, r_depth2); 60 | { 61 | tmp_vset = &vertex_set[2]; 62 | if (threadIdx.x % THREADS_PER_WARP == 0) 63 | tmp_vset->init(r_depth2 - l_depth2, &edge[l_depth2]); 64 | __threadfence_block(); 65 | if (r_depth2 - l_depth2 > vertex_set[1].get_size()) 66 | tmp_vset->size -= unordered_subtraction_size(*tmp_vset, vertex_set[1], -1); 67 | else 68 | tmp_vset->size = vertex_set[1].get_size() - unordered_subtraction_size(vertex_set[1], *tmp_vset, -1); 69 | } 70 | if (vertex_set[2].get_size() == 0) continue; 71 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.push_back(v_depth2); 72 | __threadfence_block(); 73 | ans[0] = vertex_set[1].get_size() - 1; 74 | ans[1] = vertex_set[2].get_size() - 0; 75 | long long val; 76 | val = ans[0]; 77 | val = val * ans[1]; 78 | val = val * ans[1]; 79 | sum += val * 1; 80 | val = ans[1]; 81 | val = val * ans[1]; 82 | sum += val * -1; 83 | val = ans[0]; 84 | val = val * ans[1]; 85 | sum += val * -1; 86 | val = ans[1]; 87 | val = val * ans[1]; 88 | sum += val * -1; 89 | val = ans[1]; 90 | sum += val * 2; 91 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.pop_back(); 92 | __threadfence_block(); 93 | } 94 | } 95 | if (lid == 0) atomicAdd(context->dev_sum, sum); 96 | } 97 | -------------------------------------------------------------------------------- /auto/patents_p3.cu: -------------------------------------------------------------------------------- 1 | __global__ void gpu_pattern_matching_generated(e_index_t edge_num, uint32_t buffer_size, PatternMatchingDeviceContext *context) { 2 | __shared__ e_index_t block_edge_idx[WARPS_PER_BLOCK]; 3 | extern __shared__ GPUVertexSet block_vertex_set[]; 4 | GPUSchedule *schedule = context->dev_schedule; 5 | uint32_t *tmp = context->dev_tmp; 6 | uint32_t *edge = (uint32_t *)context->dev_edge; 7 | e_index_t *vertex = context->dev_vertex; 8 | uint32_t *edge_from = (uint32_t *)context->dev_edge_from; 9 | int wid = threadIdx.x / THREADS_PER_WARP, lid = threadIdx.x % THREADS_PER_WARP, global_wid = blockIdx.x * WARPS_PER_BLOCK + wid; 10 | e_index_t &edge_idx = block_edge_idx[wid]; 11 | GPUVertexSet *vertex_set = block_vertex_set + wid * 5; 12 | if (lid == 0) { 13 | edge_idx = 0; 14 | uint32_t offset = buffer_size * global_wid * 5; 15 | for (int i = 0; i < 5; ++i) { 16 | vertex_set[i].set_data_ptr(tmp + offset); 17 | offset += buffer_size; 18 | } 19 | } 20 | GPUVertexSet& subtraction_set = vertex_set[3]; 21 | __threadfence_block(); 22 | uint32_t v0, v1; 23 | e_index_t l, r; 24 | unsigned long long sum = 0; 25 | while (true) { 26 | if (lid == 0) { 27 | edge_idx = atomicAdd(context->dev_cur_edge, 1); 28 | unsigned int i = edge_idx; 29 | if (i < edge_num) { 30 | subtraction_set.init(); 31 | subtraction_set.push_back(edge_from[i]); 32 | subtraction_set.push_back(edge[i]); 33 | } 34 | } 35 | __threadfence_block(); 36 | e_index_t i = edge_idx; 37 | if(i >= edge_num) break; 38 | v0 = edge_from[i]; 39 | v1 = edge[i]; 40 | get_edge_index(v0, l, r); 41 | if (threadIdx.x % THREADS_PER_WARP == 0) 42 | vertex_set[0].init(r - l, &edge[l]); 43 | __threadfence_block(); 44 | if(v0 <= v1) continue; 45 | get_edge_index(v1, l, r); 46 | GPUVertexSet* tmp_vset; 47 | intersection2(vertex_set[1].get_data_ptr(), vertex_set[0].get_data_ptr(), &edge[l], vertex_set[0].get_size(), r - l, &vertex_set[1].size); 48 | if (vertex_set[1].get_size() == 0) continue; 49 | extern __shared__ char ans_array[]; 50 | int* ans = ((int*) (ans_array + 576)) + 2 * (threadIdx.x / THREADS_PER_WARP); 51 | int loop_size_depth2 = vertex_set[1].get_size(); 52 | if( loop_size_depth2 <= 0) continue; 53 | uint32_t* loop_data_ptr_depth2 = vertex_set[1].get_data_ptr(); 54 | uint32_t min_vertex_depth2 = 0xffffffff; 55 | for(int i_depth2 = 0; i_depth2 < loop_size_depth2; ++i_depth2) { 56 | uint32_t v_depth2 = loop_data_ptr_depth2[i_depth2]; 57 | if(subtraction_set.has_data(v_depth2)) continue; 58 | unsigned int l_depth2, r_depth2; 59 | get_edge_index(v_depth2, l_depth2, r_depth2); 60 | { 61 | tmp_vset = &vertex_set[2]; 62 | if (threadIdx.x % THREADS_PER_WARP == 0) 63 | tmp_vset->init(r_depth2 - l_depth2, &edge[l_depth2]); 64 | __threadfence_block(); 65 | if (r_depth2 - l_depth2 > vertex_set[1].get_size()) 66 | tmp_vset->size -= unordered_subtraction_size(*tmp_vset, vertex_set[1], -1); 67 | else 68 | tmp_vset->size = vertex_set[1].get_size() - unordered_subtraction_size(vertex_set[1], *tmp_vset, -1); 69 | } 70 | if (vertex_set[2].get_size() == 0) continue; 71 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.push_back(v_depth2); 72 | __threadfence_block(); 73 | ans[0] = vertex_set[1].get_size() - 1; 74 | ans[1] = vertex_set[2].get_size() - 0; 75 | long long val; 76 | val = ans[0]; 77 | val = val * ans[1]; 78 | val = val * ans[1]; 79 | sum += val * 1; 80 | val = ans[1]; 81 | val = val * ans[1]; 82 | sum += val * -1; 83 | val = ans[0]; 84 | val = val * ans[1]; 85 | sum += val * -1; 86 | val = ans[1]; 87 | val = val * ans[1]; 88 | sum += val * -1; 89 | val = ans[1]; 90 | sum += val * 2; 91 | if (threadIdx.x % THREADS_PER_WARP == 0) subtraction_set.pop_back(); 92 | __threadfence_block(); 93 | } 94 | } 95 | if (lid == 0) atomicAdd(context->dev_sum, sum); 96 | } 97 | -------------------------------------------------------------------------------- /code_gen/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_EXECUTABLE(final_generator final_generator.cu) 2 | SET_PROPERTY(TARGET final_generator PROPERTY CUDA_SEPARABLE_COMPILATION ON) 3 | TARGET_LINK_LIBRARIES(final_generator graph_mining) 4 | -------------------------------------------------------------------------------- /compile_flags.txt: -------------------------------------------------------------------------------- 1 | -xc++ 2 | -std=c++11 3 | -Iinclude 4 | -------------------------------------------------------------------------------- /dataset/wiki-vote.g: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sth1997/GraphSet/3bc6e6b9e2e0f61ba799a9c25cab96a9da6b4dc8/dataset/wiki-vote.g -------------------------------------------------------------------------------- /env.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | source /opt/spack/share/spack/setup-env.sh 3 | spack load cuda@12.0 4 | spack load cmake@3.26 5 | spack load openmpi@4.1.5 -------------------------------------------------------------------------------- /gpu/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_EXECUTABLE(gpu_graph gpu_graph.cu) 2 | SET_PROPERTY(TARGET gpu_graph PROPERTY CUDA_SEPARABLE_COMPILATION ON) 3 | TARGET_LINK_LIBRARIES(gpu_graph graph_mining) 4 | 5 | ADD_EXECUTABLE(gpu_clique gpu_clique.cu) 6 | SET_PROPERTY(TARGET gpu_clique PROPERTY CUDA_SEPARABLE_COMPILATION ON) 7 | TARGET_LINK_LIBRARIES(gpu_clique graph_mining) 8 | 9 | ADD_EXECUTABLE(gpu_graph_mpi gpu_graph_mpi.cu) 10 | SET_PROPERTY(TARGET gpu_graph_mpi PROPERTY CUDA_SEPARABLE_COMPILATION ON) 11 | TARGET_LINK_LIBRARIES(gpu_graph_mpi graph_mining mpi gomp) 12 | 13 | ADD_EXECUTABLE(gpu_kclique gpu_kclique.cu) 14 | SET_PROPERTY(TARGET gpu_kclique PROPERTY CUDA_SEPARABLE_COMPILATION ON) 15 | TARGET_LINK_LIBRARIES(gpu_kclique graph_mining) 16 | 17 | ADD_EXECUTABLE(gpu_mc gpu_mc.cu) 18 | SET_PROPERTY(TARGET gpu_mc PROPERTY CUDA_SEPARABLE_COMPILATION ON) 19 | TARGET_LINK_LIBRARIES(gpu_mc graph_mining) 20 | 21 | ADD_EXECUTABLE(gpu_graph_unimem gpu_graph_unimem.cu) 22 | SET_PROPERTY(TARGET gpu_graph_unimem PROPERTY CUDA_SEPARABLE_COMPILATION ON) 23 | TARGET_LINK_LIBRARIES(gpu_graph_unimem graph_mining mpi gomp) 24 | 25 | ADD_EXECUTABLE(fsm_mixed fsm_mixed.cu) 26 | SET_PROPERTY(TARGET fsm_mixed PROPERTY CUDA_SEPARABLE_COMPILATION ON) 27 | TARGET_LINK_LIBRARIES(fsm_mixed graph_mining) 28 | 29 | ADD_EXECUTABLE(gpu_new_str gpu_new_str.cu) 30 | SET_PROPERTY(TARGET gpu_new_str PROPERTY CUDA_SEPARABLE_COMPILATION ON) 31 | TARGET_LINK_LIBRARIES(gpu_new_str graph_mining mpi gomp) 32 | 33 | ADD_EXECUTABLE(gpu_fsm gpu_fsm.cu) 34 | SET_PROPERTY(TARGET gpu_fsm PROPERTY CUDA_SEPARABLE_COMPILATION ON) 35 | TARGET_LINK_LIBRARIES(gpu_fsm graph_mining) 36 | 37 | ADD_EXECUTABLE(gpu_new_fsm gpu_new_fsm.cu) 38 | SET_PROPERTY(TARGET gpu_new_fsm PROPERTY CUDA_SEPARABLE_COMPILATION ON) 39 | TARGET_LINK_LIBRARIES(gpu_new_fsm graph_mining) 40 | 41 | ADD_EXECUTABLE(gpu_fsm_omp gpu_fsm_omp.cu) 42 | SET_PROPERTY(TARGET gpu_fsm_omp PROPERTY CUDA_SEPARABLE_COMPILATION ON) 43 | TARGET_LINK_LIBRARIES(gpu_fsm_omp graph_mining) 44 | 45 | ADD_EXECUTABLE(gpu_graph_static_task gpu_graph_static_task.cu) 46 | SET_PROPERTY(TARGET gpu_graph_static_task PROPERTY CUDA_SEPARABLE_COMPILATION ON) 47 | TARGET_LINK_LIBRARIES(gpu_graph_static_task graph_mining mpi gomp) 48 | 49 | find_package(OpenMP) 50 | if(OpenMP_CXX_FOUND) 51 | target_link_libraries(gpu_new_str OpenMP::OpenMP_CXX) 52 | target_link_libraries(gpu_fsm_omp OpenMP::OpenMP_CXX) 53 | target_link_libraries(gpu_kclique OpenMP::OpenMP_CXX) 54 | target_link_libraries(gpu_graph_mpi OpenMP::OpenMP_CXX) 55 | target_link_libraries(gpu_graph_unimem OpenMP::OpenMP_CXX) 56 | target_link_libraries(gpu_new_fsm OpenMP::OpenMP_CXX) 57 | target_link_libraries(fsm_mixed OpenMP::OpenMP_CXX) 58 | endif() 59 | 60 | ADD_EXECUTABLE(mc3 mc3.cu) 61 | SET_PROPERTY(TARGET mc3 PROPERTY CUDA_SEPARABLE_COMPILATION ON) 62 | TARGET_LINK_LIBRARIES(mc3 graph_mining) 63 | -------------------------------------------------------------------------------- /gpu/component/gpu_bitvector.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | #include 5 | 6 | #include "gpu_const.cuh" 7 | #include "utils.cuh" 8 | 9 | class GPUBitVector { 10 | public: 11 | GPUBitVector &operator=(const GPUBitVector &) = delete; 12 | GPUBitVector(const GPUBitVector &&) = delete; 13 | GPUBitVector(const GPUBitVector &) = delete; 14 | 15 | void construct(size_t element_cnt) { 16 | size = (element_cnt + 31) / 32; 17 | gpuErrchk(cudaMalloc((void **)&data, size * sizeof(uint32_t))); 18 | } 19 | void destroy() { gpuErrchk(cudaFree(data)); } 20 | 21 | __device__ void clear() { 22 | non_zero_cnt = 0; 23 | memset((void *)data, 0, size * sizeof(uint32_t)); 24 | } 25 | 26 | inline __device__ uint32_t &operator[](const int index) { return data[index]; } 27 | 28 | inline __device__ uint32_t calculate_non_zero_cnt() const { 29 | // warp reduce version 30 | typedef cub::WarpReduce WarpReduce; 31 | __shared__ typename WarpReduce::TempStorage temp_storage[WARPS_PER_BLOCK]; 32 | int wid = threadIdx.x / THREADS_PER_WARP; // warp id 33 | int lid = threadIdx.x % THREADS_PER_WARP; // lane id 34 | uint32_t sum = 0; 35 | for (int index = 0; index < size; index += THREADS_PER_WARP) 36 | if (index + lid < size) 37 | sum += __popc(data[index + lid]); 38 | __syncwarp(); 39 | uint32_t aggregate = WarpReduce(temp_storage[wid]).Sum(sum); 40 | __syncwarp(); 41 | // brute force version 42 | // uint32_t aggregate = 0; 43 | // for(int index = 0; index < size; index++){ 44 | // aggregate += __popc(data[index]); 45 | // } 46 | return aggregate; 47 | } 48 | inline __device__ uint32_t get_non_zero_cnt() const { return non_zero_cnt; } 49 | 50 | __device__ void insert(uint32_t id) { 51 | // data[id >> 5] |= 1 << (id & 31); 52 | atomicOr(&data[id >> 5], 1 << (id & 31)); 53 | __threadfence_block(); 54 | } 55 | __device__ uint32_t insert_and_update(uint32_t id) { 56 | uint32_t index = id >> 5; 57 | uint32_t tmp_data = data[index]; 58 | uint32_t offset = 1 << (id % 32); 59 | if ((tmp_data & offset) == 0) { 60 | ++non_zero_cnt; 61 | data[index] = tmp_data | offset; 62 | } 63 | } 64 | __host__ __device__ uint32_t *get_data() const { return data; } 65 | __host__ __device__ size_t get_size() const { return size; } 66 | 67 | private: 68 | size_t size; 69 | uint32_t *data; 70 | uint32_t non_zero_cnt; 71 | }; -------------------------------------------------------------------------------- /gpu/component/gpu_const.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | constexpr int THREADS_PER_BLOCK = 128; 4 | constexpr int THREADS_PER_WARP = 32; 5 | constexpr int WARPS_PER_BLOCK = THREADS_PER_BLOCK / THREADS_PER_WARP; 6 | 7 | constexpr int num_blocks = 1024; 8 | constexpr int num_total_warps = num_blocks * WARPS_PER_BLOCK; 9 | constexpr double cpu_proportion = 0.9; 10 | 11 | void print_parameter() { 12 | printf("THREADS_PER_BLOCK = %d\n", THREADS_PER_BLOCK); 13 | printf("THREADS_PER_WARP = %d\n", THREADS_PER_WARP); 14 | printf("num_blocks = %d\n", num_blocks); 15 | printf("cpu_proportion = %lf\n", cpu_proportion); 16 | } -------------------------------------------------------------------------------- /gpu/component/gpu_device_context.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "graph.h" 6 | #include "labeled_graph.h" 7 | 8 | struct GPUDeviceContext { 9 | int32_t dev_id; 10 | }; 11 | 12 | struct GraphDeviceContext : public GPUDeviceContext { 13 | v_index_t *dev_edge, *dev_edge_from; 14 | e_index_t *dev_vertex; 15 | uint32_t *dev_tmp; 16 | const Graph *g; 17 | }; 18 | 19 | struct LabeledGraphDeviceContext : public GPUDeviceContext { 20 | uint32_t *dev_edge; 21 | uint32_t *dev_labeled_vertex; 22 | int32_t *dev_v_label; 23 | const LabeledGraph *g; 24 | }; -------------------------------------------------------------------------------- /gpu/component/gpu_device_detect.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | int get_device_information(bool print = false) { 5 | int nDevices; 6 | cudaGetDeviceCount(&nDevices); 7 | if(print) std::cerr << "Device Information:" << std::endl; 8 | for (int i = 0; i < nDevices; i++) { 9 | cudaDeviceProp prop; 10 | cudaGetDeviceProperties(&prop, i); 11 | if(print) std::cerr << "Device " << i << ", name: " << prop.name << std::endl; 12 | if (i == 0) { 13 | if(print) std::cerr << " Memory Clock Rate (KHz): " << prop.memoryClockRate << std::endl; 14 | if(print) std::cerr << " Memory Bus Width (bits): " << prop.memoryBusWidth << std::endl; 15 | if(print) std::cerr.precision(2); 16 | if(print) std::cerr << " Peak Memory Bandwidth (GB/s): " << 2.0 * prop.memoryClockRate * (prop.memoryBusWidth / 8) / 1.0e6 << std::endl; 17 | } 18 | } 19 | return nDevices; 20 | } -------------------------------------------------------------------------------- /gpu/component/utils.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define likely(x) __builtin_expect(!!(x), 1) 4 | #define unlikely(x) __builtin_expect(!!(x), 0) 5 | #define gpuErrchk(ans) \ 6 | { gpuAssert((ans), __FILE__, __LINE__); } 7 | inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort = true) { 8 | if (code != cudaSuccess) { 9 | fprintf(stderr, "GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line); 10 | if (abort) 11 | exit(code); 12 | } 13 | } 14 | 15 | template 16 | __device__ __host__ inline void swap(T &a, T &b) { 17 | T t(std::move(a)); 18 | a = std::move(b); 19 | b = std::move(t); 20 | } 21 | 22 | struct GPUGroupDim2 { 23 | int *data; 24 | int size; 25 | }; 26 | 27 | struct GPUGroupDim1 { 28 | GPUGroupDim2 *data; 29 | int size; 30 | }; 31 | 32 | struct GPUGroupDim0 { 33 | GPUGroupDim1 *data; 34 | int size; 35 | }; 36 | 37 | #define get_labeled_edge_index(v, label, l, r) \ 38 | do { \ 39 | int index = v * l_cnt + label; \ 40 | l = labeled_vertex[index]; \ 41 | r = labeled_vertex[index + 1]; \ 42 | } while (0) 43 | 44 | #define get_edge_index(v, l, r) \ 45 | do { \ 46 | l = vertex[v]; \ 47 | r = vertex[v + 1]; \ 48 | } while (0) 49 | 50 | void dev_alloc_and_copy(void **dst, size_t size, const void *src = nullptr) { 51 | gpuErrchk(cudaMalloc(dst, size)); 52 | if (src != nullptr) { 53 | gpuErrchk(cudaMemcpy(*dst, src, size, cudaMemcpyHostToDevice)); 54 | } 55 | } 56 | 57 | __device__ int lower_bound(const uint32_t *loop_data_ptr, int loop_size, int min_vertex) { 58 | int l = 0, r = loop_size - 1; 59 | while (l <= r) { 60 | int mid = r - ((r - l) >> 1); 61 | if (loop_data_ptr[mid] < min_vertex) 62 | l = mid + 1; 63 | else 64 | r = mid - 1; 65 | } 66 | return l; 67 | } 68 | 69 | template 70 | __device__ bool binary_search(const T data[], int n, const T &target) { 71 | int mid, l = 0, r = n - 1; 72 | while (l <= r) { 73 | mid = (l + r) >> 1; 74 | if (data[mid] < target) { 75 | l = mid + 1; 76 | } else if (data[mid] > target) { 77 | r = mid - 1; 78 | } else { 79 | return true; 80 | } 81 | } 82 | return false; 83 | } 84 | 85 | #define log(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__);fflush(stderr) 86 | // #define log(fmt, ...) (void)(fmt) 87 | 88 | -------------------------------------------------------------------------------- /gpu/gpu_graph.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common.h" 8 | #include "dataloader.h" 9 | #include "graph.h" 10 | #include "motif_generator.h" 11 | #include "schedule_IEP.h" 12 | #include "vertex_set.h" 13 | #include "timeinterval.h" 14 | 15 | #include "component/gpu_device_detect.cuh" 16 | #include "src/gpu_pattern_matching.cuh" 17 | 18 | 19 | TimeInterval allTime; 20 | TimeInterval tmpTime; 21 | 22 | void pattern_matching(Graph *g, const Schedule_IEP &schedule_iep) { 23 | tmpTime.check(); 24 | PatternMatchingDeviceContext *context; 25 | gpuErrchk(cudaMallocManaged((void **)&context, sizeof(PatternMatchingDeviceContext))); 26 | context->init(g, schedule_iep); 27 | 28 | uint32_t buffer_size = VertexSet::max_intersection_size; 29 | int max_active_blocks_per_sm; 30 | cudaOccupancyMaxActiveBlocksPerMultiprocessor(&max_active_blocks_per_sm, gpu_pattern_matching, THREADS_PER_BLOCK, context->block_shmem_size); 31 | fprintf(stderr, "max number of active warps per SM: %d\n", max_active_blocks_per_sm * WARPS_PER_BLOCK); 32 | 33 | tmpTime.print("Prepare time cost"); 34 | tmpTime.check(); 35 | 36 | unsigned long long sum = 0; 37 | 38 | gpu_pattern_matching<<block_shmem_size>>>(g->e_cnt, buffer_size, context); 39 | 40 | gpuErrchk(cudaPeekAtLastError()); 41 | gpuErrchk(cudaDeviceSynchronize()); 42 | gpuErrchk(cudaMemcpy(&sum, context->dev_sum, sizeof(sum), cudaMemcpyDeviceToHost)); 43 | 44 | sum /= schedule_iep.get_in_exclusion_optimize_redundancy(); 45 | 46 | printf("Pattern count: %llu\n", sum); 47 | tmpTime.print("Counting time cost"); 48 | 49 | context->destroy(); 50 | gpuErrchk(cudaFree(context)); 51 | } 52 | 53 | int main(int argc, char *argv[]) { 54 | get_device_information(); 55 | Graph *g; 56 | DataLoader D; 57 | 58 | if (argc < 4) { 59 | fprintf(stderr, "Usage: %s graph_file pattern_size pattern_string <1/0 for enable iep or not>\n", argv[0]); 60 | return 1; 61 | } 62 | 63 | int enable_iep = 1; 64 | if(argc >= 5) { 65 | enable_iep = atoi(argv[4]); 66 | if(enable_iep != 0 && enable_iep != 1) { 67 | fprintf(stderr, "Usage: %s graph_file pattern_size pattern_string <1/0 for enable iep or not>\n", argv[0]); 68 | return 1; 69 | } else { 70 | fprintf(stderr, "Enable iep: %d\n", enable_iep); 71 | } 72 | } 73 | 74 | using std::chrono::system_clock; 75 | auto t1 = system_clock::now(); 76 | 77 | bool ok = D.fast_load(g, argv[1]); 78 | if (!ok) { 79 | fprintf(stderr, "data load failure :-(\n"); 80 | return 0; 81 | } 82 | 83 | auto t2 = system_clock::now(); 84 | auto load_time = std::chrono::duration_cast(t2 - t1); 85 | fprintf(stderr, "Load data success! time: %g seconds\n", load_time.count() / 1.0e6); 86 | 87 | allTime.check(); 88 | 89 | int pattern_size = atoi(argv[2]); 90 | const char *pattern_str = argv[3]; 91 | 92 | Pattern p(pattern_size, pattern_str); 93 | 94 | printf("pattern = "); 95 | p.print(); 96 | 97 | fprintf(stderr, "Max intersection size %d\n", VertexSet::max_intersection_size); 98 | 99 | tmpTime.check(); 100 | 101 | bool is_pattern_valid; 102 | Schedule_IEP schedule_iep(p, is_pattern_valid, 1, 1, enable_iep, g->v_cnt, g->e_cnt, g->tri_cnt); 103 | if (!is_pattern_valid) { 104 | fprintf(stderr, "pattern is invalid!\n"); 105 | return 1; 106 | } 107 | 108 | tmpTime.print("Schedule time cost"); 109 | 110 | pattern_matching(g, schedule_iep); 111 | 112 | allTime.print("Total time cost"); 113 | return 0; 114 | } 115 | -------------------------------------------------------------------------------- /gpu/gpu_mc.cu: -------------------------------------------------------------------------------- 1 | /** 2 | * 这个版本里面没有细粒度计时。有计时的在gpu_graph_with_timer.cu里面。 3 | * 而且计时的方式与zms版本略有区别。 4 | */ 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "graph.h" 12 | #include "dataloader.h" 13 | #include "vertex_set.h" 14 | #include "common.h" 15 | #include "schedule_IEP.h" 16 | #include "motif_generator.h" 17 | #include "timeinterval.h" 18 | 19 | #include "component/utils.cuh" 20 | #include "component/gpu_schedule.cuh" 21 | #include "component/gpu_vertex_set.cuh" 22 | #include "function/pattern_matching.cuh" 23 | #include "src/gpu_pattern_matching.cuh" 24 | 25 | TimeInterval allTime; 26 | TimeInterval tmpTime; 27 | 28 | // same as gpu_graph 29 | double pattern_matching(Graph *g, const Schedule_IEP &schedule_iep) { 30 | tmpTime.check(); 31 | PatternMatchingDeviceContext *context; 32 | gpuErrchk(cudaMallocManaged((void **)&context, sizeof(PatternMatchingDeviceContext))); 33 | context->init(g, schedule_iep); 34 | 35 | uint32_t buffer_size = VertexSet::max_intersection_size; 36 | int max_active_blocks_per_sm; 37 | cudaOccupancyMaxActiveBlocksPerMultiprocessor(&max_active_blocks_per_sm, gpu_pattern_matching, THREADS_PER_BLOCK, context->block_shmem_size); 38 | fprintf(stderr, "max number of active warps per SM: %d\n", max_active_blocks_per_sm * WARPS_PER_BLOCK); 39 | 40 | tmpTime.print("Prepare time cost"); 41 | tmpTime.check(); 42 | 43 | unsigned long long sum = 0; 44 | 45 | gpu_pattern_matching<<block_shmem_size>>>(g->e_cnt, buffer_size, context); 46 | 47 | gpuErrchk(cudaPeekAtLastError()); 48 | gpuErrchk(cudaDeviceSynchronize()); 49 | gpuErrchk(cudaMemcpy(&sum, context->dev_sum, sizeof(sum), cudaMemcpyDeviceToHost)); 50 | 51 | sum /= schedule_iep.get_in_exclusion_optimize_redundancy(); 52 | 53 | printf("Pattern count: %llu\n", sum); 54 | double counting_time = tmpTime.print("Single pattern counting time cost"); 55 | 56 | context->destroy(); 57 | gpuErrchk(cudaFree(context)); 58 | return counting_time; 59 | } 60 | 61 | 62 | int main(int argc,char *argv[]) { 63 | Graph *g; 64 | DataLoader D; 65 | 66 | using std::chrono::system_clock; 67 | auto t1 = system_clock::now(); 68 | 69 | bool ok = D.fast_load(g, argv[1]); 70 | 71 | if (argc < 3) { 72 | fprintf(stderr, "Usage: %s graph_file pattern_size\n", argv[0]); 73 | return 1; 74 | } 75 | 76 | if (!ok) { 77 | fprintf(stderr, "data load failure :-(\n"); 78 | return 1; 79 | } 80 | 81 | auto t2 = system_clock::now(); 82 | auto load_time = std::chrono::duration_cast(t2 - t1); 83 | fprintf(stderr, "Load data success! time: %g seconds\n", load_time.count() / 1.0e6); 84 | 85 | allTime.check(); 86 | 87 | int pattern_size = atoi(argv[2]); 88 | 89 | printf("motif_size: %d\n", pattern_size); 90 | 91 | double total_counting_time = 0.0; 92 | 93 | MotifGenerator mg(pattern_size); 94 | std::vector motifs = mg.generate(); 95 | printf("Motifs number = %d\n", motifs.size()); 96 | for (int i = 0; i < motifs.size(); ++i) { 97 | Pattern p(motifs[i]); 98 | 99 | printf("pattern = "); 100 | p.print(); 101 | 102 | fprintf(stderr, "max intersection size %d\n", VertexSet::max_intersection_size); 103 | 104 | bool is_pattern_valid; 105 | bool use_in_exclusion_optimize = true; 106 | Schedule_IEP schedule_iep(p, is_pattern_valid, 1, 1, true, g->v_cnt, g->e_cnt, g->tri_cnt); 107 | 108 | if (!is_pattern_valid) { 109 | fprintf(stderr, "pattern is invalid!\n"); 110 | return 1; 111 | } 112 | 113 | total_counting_time += pattern_matching(g, schedule_iep); 114 | 115 | } 116 | printf("Counting time cost: %.6lf s\n", total_counting_time); 117 | allTime.print("Total time cost"); 118 | return 0; 119 | } -------------------------------------------------------------------------------- /gpu/gpu_test.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "component/utils.cuh" 3 | 4 | __global__ void kernel_function(int n, int *a, int *b) { 5 | int pos = blockIdx.x * blockDim.x + threadIdx.x; 6 | if(pos >= n) return; 7 | a[pos] += b[pos]; 8 | } 9 | 10 | void test(int n, int *a, int *b) { 11 | const int BLOCK_NUM = 1000, BLOCK_SIZE = 128; 12 | int *dev_a, *dev_b; 13 | gpuErrchk( cudaMalloc((void **)&dev_a, sizeof(int) * n) ); 14 | gpuErrchk( cudaMalloc((void **)&dev_b, sizeof(int) * n) ); 15 | gpuErrchk( cudaMemcpy(dev_a, a, sizeof(int) * n, cudaMemcpyHostToDevice) ); 16 | gpuErrchk( cudaMemcpy(dev_b, b, sizeof(int) * n, cudaMemcpyHostToDevice) ); 17 | kernel_function<<>>(n,dev_a,dev_b); 18 | for(int i = 0; i < n; i++) { 19 | a[i] = a[i] + b[i]; 20 | } 21 | 22 | gpuErrchk( cudaPeekAtLastError() ); 23 | gpuErrchk( cudaDeviceSynchronize() ); 24 | 25 | gpuErrchk( cudaMemcpy(b, dev_a, sizeof(int) * n, cudaMemcpyDeviceToHost) ); 26 | 27 | } -------------------------------------------------------------------------------- /gpu/src/gpu_pattern_matching.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../component/gpu_device_context.cuh" 3 | #include "../component/gpu_schedule.cuh" 4 | #include "../component/gpu_vertex_set.cuh" 5 | #include "../component/utils.cuh" 6 | 7 | #include "../function/pattern_matching.cuh" 8 | 9 | /** 10 | * @note `buffer_size`实际上是每个节点的最大邻居数量,而非所用空间大小 11 | * 12 | * 当用作 MPI 的时候,edge_num 指的是结束的边的编号,此时 dev_cur_edge 初始值并不为 0. 13 | */ 14 | __global__ void gpu_pattern_matching(e_index_t edge_num, uint32_t buffer_size, PatternMatchingDeviceContext *context) { 15 | __shared__ e_index_t block_edge_idx[WARPS_PER_BLOCK]; 16 | //之后考虑把tmp buffer都放到shared里来(如果放得下) 17 | extern __shared__ GPUVertexSet block_vertex_set[]; 18 | 19 | GPUSchedule *schedule = context->dev_schedule; 20 | uint32_t *tmp = context->dev_tmp; 21 | uint32_t *edge = (uint32_t *)context->dev_edge; 22 | e_index_t *vertex = context->dev_vertex; 23 | uint32_t *edge_from = (uint32_t *)context->dev_edge_from; 24 | 25 | int num_prefixes = schedule->get_total_prefix_num(); 26 | int num_vertex_sets_per_warp = num_prefixes + 2; 27 | // extra n-2 vertex_sets for vertex_induced (motif counting) 28 | if(schedule->is_vertex_induced) num_vertex_sets_per_warp += schedule->get_size() - 2; 29 | 30 | int wid = threadIdx.x / THREADS_PER_WARP; // warp id within the block 31 | int lid = threadIdx.x % THREADS_PER_WARP; // lane id 32 | int global_wid = blockIdx.x * WARPS_PER_BLOCK + wid; // global warp id 33 | e_index_t &edge_idx = block_edge_idx[wid]; 34 | GPUVertexSet *vertex_set = block_vertex_set + wid * num_vertex_sets_per_warp; 35 | 36 | if (lid == 0) { 37 | edge_idx = 0; 38 | uint32_t offset = buffer_size * global_wid * num_vertex_sets_per_warp; 39 | for (int i = 0; i < num_vertex_sets_per_warp; ++i) { 40 | vertex_set[i].set_data_ptr(tmp + offset); // 注意这是个指针+整数运算,自带*4 41 | offset += buffer_size; 42 | } 43 | } 44 | GPUVertexSet &subtraction_set = vertex_set[num_prefixes]; 45 | GPUVertexSet &tmp_set = vertex_set[num_prefixes + 1]; 46 | 47 | __threadfence_block(); //之后考虑把所有的syncthreads都改成syncwarp 48 | 49 | uint32_t v0, v1; 50 | e_index_t l, r; 51 | 52 | unsigned long long sum = 0; 53 | 54 | while (true) { 55 | if (lid == 0) { 56 | edge_idx = atomicAdd(context->dev_cur_edge, 1); 57 | e_index_t i = edge_idx; 58 | if (i < edge_num) { 59 | subtraction_set.init(); 60 | subtraction_set.push_back(edge_from[i]); 61 | subtraction_set.push_back(edge[i]); 62 | } 63 | } 64 | 65 | __threadfence_block(); 66 | 67 | e_index_t i = edge_idx; 68 | if (i >= edge_num) 69 | break; 70 | 71 | // for edge in E 72 | v0 = edge_from[i]; 73 | v1 = edge[i]; 74 | 75 | //目前只考虑pattern size>2的情况 76 | // start v1, depth = 1 77 | if (schedule->get_restrict_last(1) != -1 && v0 <= v1) 78 | continue; 79 | 80 | bool is_zero = false; 81 | get_edge_index(v0, l, r); 82 | for (int prefix_id = schedule->get_last(0); prefix_id != -1; prefix_id = schedule->get_next(prefix_id)) 83 | vertex_set[prefix_id].build_vertex_set(schedule, vertex_set, &edge[l], r - l, prefix_id); 84 | 85 | get_edge_index(v1, l, r); 86 | for (int prefix_id = schedule->get_last(1); prefix_id != -1; prefix_id = schedule->get_next(prefix_id)) { 87 | vertex_set[prefix_id].build_vertex_set(schedule, vertex_set, &edge[l], r - l, prefix_id); 88 | if (vertex_set[prefix_id].get_size() == 0 && prefix_id < schedule->get_basic_prefix_num()) { 89 | is_zero = true; 90 | break; 91 | } 92 | } 93 | if (is_zero) 94 | continue; 95 | 96 | unsigned long long local_sum = 0; // local sum (corresponding to an edge index) 97 | GPU_pattern_matching_func<2>(schedule, vertex_set, subtraction_set, tmp_set, local_sum, edge, vertex); 98 | sum += local_sum; 99 | } 100 | 101 | if (lid == 0) { 102 | atomicAdd(context->dev_sum, sum); 103 | } 104 | } -------------------------------------------------------------------------------- /gpu/src/gpu_pattern_matching_static_task.cuh: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "../component/gpu_device_context.cuh" 3 | #include "../component/gpu_schedule.cuh" 4 | #include "../component/gpu_vertex_set.cuh" 5 | #include "../component/utils.cuh" 6 | 7 | #include "../function/pattern_matching.cuh" 8 | 9 | /** 10 | * @note `buffer_size`实际上是每个节点的最大邻居数量,而非所用空间大小 11 | * 12 | * 当用作 MPI 的时候,edge_num 指的是结束的边的编号,此时 dev_cur_edge 初始值并不为 0. 13 | */ 14 | __global__ void gpu_pattern_matching_static(e_index_t edge_num, uint32_t buffer_size, uint32_t chunk_size, PatternMatchingDeviceContext *context) { 15 | __shared__ e_index_t block_edge_idx[WARPS_PER_BLOCK]; 16 | //之后考虑把tmp buffer都放到shared里来(如果放得下) 17 | extern __shared__ GPUVertexSet block_vertex_set[]; 18 | 19 | GPUSchedule *schedule = context->dev_schedule; 20 | uint32_t *tmp = context->dev_tmp; 21 | uint32_t *edge = (uint32_t *)context->dev_edge; 22 | e_index_t *vertex = context->dev_vertex; 23 | uint32_t *edge_from = (uint32_t *)context->dev_edge_from; 24 | e_index_t *new_order = (e_index_t *)context->dev_new_order; 25 | 26 | int32_t no_devices = context->devices_no; 27 | int32_t total_devices = context->devices_num; 28 | 29 | int num_prefixes = schedule->get_total_prefix_num(); 30 | int num_vertex_sets_per_warp = num_prefixes + 2; 31 | 32 | int wid = threadIdx.x / THREADS_PER_WARP; // warp id within the block 33 | int lid = threadIdx.x % THREADS_PER_WARP; // lane id 34 | int global_wid = blockIdx.x * WARPS_PER_BLOCK + wid; // global warp id 35 | e_index_t &edge_idx = block_edge_idx[wid]; 36 | GPUVertexSet *vertex_set = block_vertex_set + wid * num_vertex_sets_per_warp; 37 | 38 | if (lid == 0) { 39 | edge_idx = 0; 40 | uint32_t offset = buffer_size * global_wid * num_vertex_sets_per_warp; 41 | for (int i = 0; i < num_vertex_sets_per_warp; ++i) { 42 | vertex_set[i].set_data_ptr(tmp + offset); // 注意这是个指针+整数运算,自带*4 43 | offset += buffer_size; 44 | } 45 | } 46 | GPUVertexSet &subtraction_set = vertex_set[num_prefixes]; 47 | GPUVertexSet &tmp_set = vertex_set[num_prefixes + 1]; 48 | 49 | __threadfence_block(); //之后考虑把所有的syncthreads都改成syncwarp 50 | 51 | uint32_t v0, v1; 52 | e_index_t l, r; 53 | 54 | unsigned long long sum = 0; 55 | 56 | while (true) { 57 | if (lid == 0) { 58 | edge_idx = atomicAdd(context->dev_cur_edge, 1); 59 | } 60 | __threadfence_block(); 61 | 62 | // for e in E 63 | e_index_t i = ((edge_idx / chunk_size) * total_devices + no_devices) * chunk_size + edge_idx % chunk_size; 64 | if(i >= edge_num) { 65 | break; 66 | } 67 | v0 = edge_from[i]; 68 | v1 = edge[i]; 69 | 70 | 71 | if(lid == 0) { 72 | subtraction_set.init(); 73 | subtraction_set.push_back(v0); 74 | subtraction_set.push_back(v1); 75 | } 76 | 77 | __threadfence_block(); 78 | 79 | 80 | //目前只考虑pattern size>2的情况 81 | // start v1, depth = 1 82 | if (schedule->get_restrict_last(1) != -1 && v0 <= v1) 83 | continue; 84 | 85 | bool is_zero = false; 86 | get_edge_index(v0, l, r); 87 | for (int prefix_id = schedule->get_last(0); prefix_id != -1; prefix_id = schedule->get_next(prefix_id)) 88 | vertex_set[prefix_id].build_vertex_set(schedule, vertex_set, &edge[l], r - l, prefix_id); 89 | 90 | get_edge_index(v1, l, r); 91 | for (int prefix_id = schedule->get_last(1); prefix_id != -1; prefix_id = schedule->get_next(prefix_id)) { 92 | vertex_set[prefix_id].build_vertex_set(schedule, vertex_set, &edge[l], r - l, prefix_id); 93 | if (vertex_set[prefix_id].get_size() == 0 && prefix_id < schedule->get_basic_prefix_num()) { 94 | is_zero = true; 95 | break; 96 | } 97 | } 98 | if (is_zero) 99 | continue; 100 | 101 | unsigned long long local_sum = 0; // local sum (corresponding to an edge index) 102 | GPU_pattern_matching_func<2>(schedule, vertex_set, subtraction_set, tmp_set, local_sum, edge, vertex); 103 | sum += local_sum; 104 | } 105 | 106 | if (lid == 0) { 107 | atomicAdd(context->dev_sum, sum); 108 | } 109 | } -------------------------------------------------------------------------------- /include/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pattern.h" 3 | #include "dataloader.h" 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | double get_wall_time(); 10 | 11 | void PatternType_printer(PatternType type); 12 | 13 | bool is_equal_adj_mat(const int* adj_mat1, const int* adj_mat2, int size); 14 | 15 | void GetDataType(DataType &type, const std::string str); 16 | 17 | int read_int(); 18 | 19 | unsigned int read_unsigned_int(); 20 | 21 | -------------------------------------------------------------------------------- /include/dataloader.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "graph.h" 4 | #include "labeled_graph.h" 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | enum DataType { 15 | Patents, 16 | Orkut, 17 | complete8, 18 | LiveJournal, 19 | MiCo, 20 | Twitter, 21 | CiteSeer, 22 | Wiki_Vote, 23 | YouTube, 24 | Friendster, 25 | Invalid 26 | }; 27 | 28 | constexpr long long Patents_tri_cnt = 7515023LL; 29 | constexpr long long LiveJournal_tri_cnt = 177820130LL; 30 | constexpr long long MiCo_tri_cnt = 12534960LL; 31 | constexpr long long CiteSeer_tri_cnt = 1166LL; 32 | constexpr long long Wiki_Vote_tri_cnt = 608389LL; 33 | constexpr long long Orkut_tri_cnt = 627584181LL; 34 | constexpr long long Twitter_tri_cnt = 34824916864LL; 35 | constexpr long long YouTube_tri_cnt = 103017122LL; 36 | constexpr long long Friendster_tri_cnt = 4173724142LL; 37 | 38 | class DataLoader { 39 | public: 40 | 41 | bool load_data(Graph* &g, DataType type, const char* path, bool binary_input = false, int oriented_type = 0); 42 | // binary_input: binary graph input if true, otherwise text 43 | // pattern_diameter means max distance between two vertex in graph 44 | // oriented_type is used to reorder dataset 45 | // oriented_type == 0 do nothing 46 | // == 1 high degree first 47 | // == 2 low degree first 48 | 49 | bool load_labeled_data(LabeledGraph* &g, DataType type, const char* path); 50 | 51 | bool load_data(Graph* &g, int clique_size); 52 | 53 | bool fast_load(Graph* &g, const char* path); 54 | 55 | bool load_complete(Graph* &g, int clique_size); 56 | 57 | private: 58 | static bool cmp_pair(std::paira, std::pairb); 59 | static bool cmp_tuple(std::tuplea, std::tupleb); 60 | static bool cmp_label(std::pair a,std::pair b); 61 | static bool cmp_degree_gt(std::pair a,std::pair b); 62 | static bool cmp_degree_lt(std::pair a,std::pair b); 63 | 64 | long long comb(int n,int k); 65 | bool general_load_data(Graph* &g, DataType type, const char* path, bool binary_input, int oriented_type = 0); 66 | bool twitter_load_data(Graph* &g, DataType type, const char* path, int oriented_type = 0); 67 | bool general_load_labeled_data(LabeledGraph* &g, DataType type, const char* path); 68 | 69 | std::unordered_map id; 70 | std::unordered_map label; 71 | }; 72 | -------------------------------------------------------------------------------- /include/disjoint_set_union.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class DisjointSetUnion { 4 | public: 5 | DisjointSetUnion(int n); 6 | ~DisjointSetUnion(); 7 | void init(); 8 | void merge(int id1, int id2); 9 | inline int get_set_size() const { return set_size;} 10 | inline int get_size() const { return size;} 11 | 12 | private: 13 | int get_father(int a); 14 | 15 | int size; 16 | int set_size; 17 | int* father; 18 | }; 19 | -------------------------------------------------------------------------------- /include/graph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "types.h" 3 | #include "schedule_IEP.h" 4 | #include "vertex_set.h" 5 | 6 | #include 7 | #include 8 | 9 | constexpr int chunk_size = 100; 10 | 11 | class Graphmpi; 12 | class Graph { 13 | public: 14 | v_index_t v_cnt; // number of vertex 15 | e_index_t e_cnt; // number of edge 16 | long long tri_cnt; // number of triangle 17 | double max_running_time = 60 * 60 * 24; // second 18 | v_index_t *edge, *edge_from; // edges 19 | e_index_t *vertex; // v_i's neighbor is in edge[ vertex[i], vertex[i+1]-1] 20 | 21 | Graph() { 22 | v_cnt = 0; 23 | e_cnt = 0LL; 24 | edge = nullptr; 25 | vertex = nullptr; 26 | edge_from = nullptr; 27 | } 28 | 29 | ~Graph() { 30 | if(edge != nullptr) delete[] edge; 31 | if(vertex != nullptr) delete[] vertex; 32 | if (edge_from != nullptr) delete[] edge_from; 33 | } 34 | 35 | int intersection_size(v_index_t v1,v_index_t v2); 36 | int intersection_size_mpi(v_index_t v1,v_index_t v2); 37 | int intersection_size_clique(v_index_t v1,v_index_t v2); 38 | void build_reverse_edges(); 39 | 40 | /* long long intersection_times_low; 41 | long long intersection_times_high; 42 | long long dep1_cnt; 43 | long long dep2_cnt; 44 | long long dep3_cnt; 45 | */ 46 | //single thread triangle counting 47 | long long triangle_counting(); 48 | 49 | //multi thread triangle counting 50 | long long triangle_counting_mt(); 51 | 52 | //multi thread triangle counting with mpi 53 | long long triangle_counting_mpi(); 54 | 55 | //general pattern matching algorithm with multi thread 56 | long long pattern_matching(const Schedule_IEP& schedule, bool clique = false); 57 | 58 | //general pattern matching algorithm with multi thread ans multi process 59 | long long pattern_matching_mpi(const Schedule_IEP& schedule, int thread_count, bool clique = false); 60 | 61 | // naive motif counting 62 | void motif_counting(int pattern_size); 63 | 64 | // hand optimized 3-motif counting 65 | void motif_counting_3(); 66 | 67 | // internal use only 68 | long long pattern_matching_edge_task(const Schedule_IEP& schedule, int edge_id, 69 | VertexSet vertex_sets[], VertexSet& partial_embedding, VertexSet& tmp_set, int ans_buffer[]); 70 | 71 | void get_third_layer_size(const Schedule_IEP& schedule, int *count) const; 72 | 73 | void reorder_edge(const Schedule_IEP& schedule, e_index_t * new_order, e_index_t * task_start, int total_devices) const; 74 | 75 | private: 76 | friend Graphmpi; 77 | void tc_mt(long long * global_ans); 78 | 79 | void remove_anti_edge_vertices(VertexSet& out_buf, const VertexSet& in_buf, const Schedule_IEP& sched, const VertexSet& partial_embedding, int vp); 80 | 81 | void get_edge_index(v_index_t v, e_index_t& l, e_index_t& r) const; 82 | 83 | void clique_matching_func(const Schedule_IEP& schedule, VertexSet* vertex_set, Bitmap* bs, long long& local_ans, int depth); 84 | 85 | void pattern_matching_func(const Schedule_IEP& schedule, VertexSet* vertex_set, VertexSet& subtraction_set, long long& local_ans, int depth, bool clique = false); 86 | 87 | void pattern_matching_aggressive_func(const Schedule_IEP& schedule, VertexSet* vertex_set, VertexSet& subtraction_set, VertexSet& tmp_set, long long& local_ans, int depth, int* ans_buffer); 88 | 89 | void pattern_matching_aggressive_func_mpi(const Schedule_IEP& schedule, VertexSet* vertex_set, VertexSet& subtraction_set, VertexSet &tmp_set, long long& local_ans, int depth); 90 | 91 | }; 92 | 93 | void reduce_edges_for_clique(Graph &g); 94 | 95 | void degree_orientation_init(Graph* original_g, Graph*& g); 96 | 97 | void degeneracy_orientation_init(Graph* original_g, Graph*& g); 98 | -------------------------------------------------------------------------------- /include/graphmpi.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "graph.h" 3 | #include 4 | #include 5 | 6 | class Graphmpi { 7 | public: 8 | static Graphmpi& getinstance(); 9 | std::pair init(int thread_count, Graph *graph); // get node range 10 | long long runmajor(); // mpi uses on major thread 11 | int* getneighbor(int u); // return a int[] end with a -1 12 | int getdegree(); // this function can only be called immediately after calling getneighbor 13 | bool include(int u); // return whether u is in this process 14 | std::pair get_vertex_range(); 15 | void report(long long local_ans); 16 | void end(); 17 | 18 | private: 19 | static const int MAXN = 1 << 22, MAXTHREAD = 24, chunksize = 8; 20 | Graph* graph; 21 | int comm_sz, my_rank, mynodel, mynoder, blocksize, idlethreadcnt, threadcnt, global_vertex, vertex[MAXTHREAD]; 22 | long long node_ans = 0; 23 | double starttime; 24 | std::queue requestq, idleq; 25 | static int data[MAXTHREAD][MAXN], qrynode[MAXTHREAD], qrydest[MAXTHREAD], length[MAXTHREAD]; 26 | std::atomic_flag lock[MAXTHREAD], global_vertex_lock; 27 | Graphmpi(); 28 | Graphmpi(const Graphmpi&&) = delete; 29 | Graphmpi(const Graphmpi&) = delete; 30 | Graphmpi& operator = (const Graphmpi&) = delete; 31 | ~Graphmpi(); 32 | }; 33 | -------------------------------------------------------------------------------- /include/labeled_graph.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "schedule_IEP.h" 3 | #include "vertex_set.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | 13 | 14 | class LabeledGraph { 15 | public: 16 | int v_cnt; // number of vertex 17 | unsigned int e_cnt; // number of edge 18 | unsigned int l_cnt; // number of label 19 | long long tri_cnt; // number of triangle 20 | double max_running_time = 60 * 60 * 24; // second 21 | 22 | int *edge; // edges 23 | int *v_label; 24 | int *label_frequency; //每个label的出现次数 25 | std::unordered_map label_map; 26 | 27 | unsigned int *labeled_vertex; // v_i's neighbor whose label is c is in edge[ vertex[i * maxlabel + c], vertex[i * maxlabel + c + 1]-1] 28 | unsigned int *label_start_idx; //所有节点默认按照label排序,[label_start_idx[i], label_start_idx[i + 1]) 是label为i的所有节点 29 | 30 | LabeledGraph() { 31 | v_cnt = 0; 32 | e_cnt = 0; 33 | edge = nullptr; 34 | v_label = nullptr; 35 | labeled_vertex = nullptr; 36 | label_start_idx = nullptr; 37 | } 38 | 39 | ~LabeledGraph() { 40 | if(edge != nullptr) delete[] edge; 41 | if(v_label != nullptr) delete[] v_label; 42 | if(labeled_vertex != nullptr) delete[] labeled_vertex; 43 | if(label_start_idx != nullptr) delete[] label_start_idx; 44 | } 45 | 46 | void get_edge_index(int v, int label, unsigned int& l, unsigned int& r) const; 47 | long long get_support_pattern_matching(VertexSet* vertex_set, VertexSet& subtraction_set, const Schedule_IEP& schedule, const char* p_label, std::vector >& fsm_set, long long min_support) const ; 48 | void get_support_pattern_matching_vertex(int vertex, VertexSet* vertex_set, VertexSet& subtraction_set, const Schedule_IEP& schedule, const char* p_label, std::vector >& fsm_set, int min_support) const; 49 | void get_fsm_necessary_info(std::vector& patterns, int max_edge, Schedule_IEP*& schedules, int& schedules_num, int*& mapping_start_idx, int*& mappings, unsigned int*& pattern_is_frequent_index, unsigned int*& is_frequent) const; 50 | void traverse_all_labeled_patterns(const Schedule_IEP* schedules, char* all_p_label, char* p_label, const int* mapping_start_idx, const int* mappings, const unsigned int* pattern_is_frequent_index, const unsigned int* is_frequent, int s_id, int depth, int mapping_start_idx_pos, size_t& all_p_label_idx) const; 51 | int fsm(int max_edge, long long _min_support, double *time_out = nullptr); // return the number of frequent labeled patterns with max_edge edges 52 | int fsm_pattern_matching(int job_start, int job_end, const Schedule_IEP &schedule, const char *all_p_label, std::vector > &automorphisms, unsigned int* is_frequent, unsigned int& pattern_is_frequent_index, int max_edge, int min_support) const; 53 | int fsm_vertex(int max_edge, long long _min_support, double *time_out = nullptr); 54 | int fsm_pattern_matching_vertex(int job_id, const Schedule_IEP &schedule, const char *p_label, std::vector > &automorphisms, unsigned int* is_frequent, unsigned int& pattern_is_frequent_index, int max_edge, int min_support) const; 55 | private: 56 | //bool 返回值代表是否有至少匹配到一个子图,若匹配到,上一层就可以加入set 57 | bool get_support_pattern_matching_aggressive_func(const Schedule_IEP& schedule, const char* p_label, VertexSet* vertex_set, VertexSet& subtraction_set, std::vector >& fsm_set, int depth) const; 58 | int fsm_cnt; 59 | }; -------------------------------------------------------------------------------- /include/motif_generator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "pattern.h" 3 | #include 4 | 5 | class MotifGenerator 6 | { 7 | public: 8 | MotifGenerator(int input_size): size(input_size){} 9 | std::vector generate(); 10 | private: 11 | int size; 12 | std::set< std::set > s; 13 | void generate_all_pattern(std::vector& vec, std::set edge_set, Pattern& p, int depth, int i, int j); 14 | }; -------------------------------------------------------------------------------- /include/pattern.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | #ifndef INDEX 7 | #define INDEX(x,y,n) ((x)*(n)+(y)) 8 | #endif 9 | 10 | enum PatternType { 11 | Rectangle, 12 | QG3, 13 | Pentagon, 14 | House, 15 | Hourglass, 16 | Cycle_6_Tri, 17 | Clique_7_Minus, 18 | sigmod2020_guo_q1, 19 | sigmod2020_guo_q2, 20 | sigmod2020_guo_q3, 21 | sigmod2020_guo_q4, 22 | sigmod2020_guo_q5, 23 | sigmod2020_guo_q6 24 | }; 25 | 26 | 27 | class Pattern 28 | { 29 | public: 30 | Pattern(int _size, bool clique = false); 31 | Pattern(int _size, const char* buffer); 32 | ~Pattern(); 33 | Pattern(const Pattern& p); 34 | Pattern& operator =(const Pattern&); 35 | Pattern(PatternType type); 36 | void add_edge(int x, int y); 37 | void del_edge(int x, int y); 38 | inline void add_ordered_edge(int x, int y) { adj_mat[INDEX(x, y, size)] = 1;} 39 | inline int get_size() const {return size;} 40 | inline const int* get_adj_mat_ptr() const {return adj_mat;} 41 | bool check_connected() const; 42 | void count_all_isomorphism(std::set< std::set >& s) const; 43 | void print() const; 44 | bool is_dag() const; 45 | private: 46 | void get_full_permutation(std::vector< std::vector >& vec, bool use[], std::vector tmp_vec, int depth) const; 47 | int* adj_mat; 48 | int size; 49 | }; 50 | -------------------------------------------------------------------------------- /include/prefix.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | class Prefix 4 | { 5 | public: 6 | Prefix(); 7 | ~Prefix(); 8 | void init(int input_size, const int* input_data); 9 | bool operator ==(const Prefix& pre) const; 10 | bool operator !=(const Prefix& pre) const; 11 | bool equal(int input_size, const int* input_data) const; 12 | inline int get_size() const { return size;} 13 | inline const int* get_data_ptr() const { return data;} 14 | inline int get_data(int index) const { return data[index];} 15 | void set_has_child(bool flag) { has_child = flag; } 16 | bool get_has_child() { return has_child; } 17 | void set_only_need_size(bool flag) { only_need_size = flag;} 18 | bool get_only_need_size() { return only_need_size; } 19 | 20 | private: 21 | int size; 22 | int* data; 23 | bool has_child; // if other prefix depends on this prefix, used for IEP intersection optimization 24 | bool only_need_size; 25 | }; 26 | -------------------------------------------------------------------------------- /include/timeinterval.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | class TimeInterval{ 6 | public: 7 | TimeInterval(){ 8 | check(); 9 | } 10 | 11 | void check(){ 12 | gettimeofday(&tp, NULL); 13 | } 14 | 15 | double print(const char* title){ 16 | struct timeval tp_end, tp_res; 17 | gettimeofday(&tp_end, NULL); 18 | timersub(&tp_end, &tp, &tp_res); 19 | printf("%s: %ld.%06ld s.\n", title, tp_res.tv_sec, tp_res.tv_usec); 20 | fflush(stdout); 21 | return tp_res.tv_sec + tp_res.tv_usec / 1e6; 22 | } 23 | double get_time() { 24 | struct timeval tp_end, tp_res; 25 | gettimeofday(&tp_end, NULL); 26 | timersub(&tp_end, &tp, &tp_res); 27 | return tp_res.tv_sec + tp_res.tv_usec / 1e6; 28 | } 29 | private: 30 | struct timeval tp; 31 | }; 32 | -------------------------------------------------------------------------------- /include/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | typedef int32_t v_index_t; 4 | typedef int64_t e_index_t; -------------------------------------------------------------------------------- /include/vertex_set.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "schedule_IEP.h" 3 | #include 4 | #include 5 | 6 | void long_add(long long &low, long long &high, int num); 7 | 8 | struct Bitmap{ 9 | uint8_t *s; 10 | int size; 11 | Bitmap(int _size): s(nullptr) { s = new uint8_t[size = _size]; set_0(); } 12 | ~Bitmap() { delete[] s; } 13 | inline void set(int pos, int v) { s[pos] = v;} 14 | inline void inc(int pos) { s[pos]++; } 15 | inline void dec(int pos) { s[pos]--; } 16 | inline uint8_t read(int pos) { return s[pos];} 17 | inline void set_bit(int pos) { s[pos] |= 1; } 18 | // inline void reset_bit(int pos) { s[pos / 64] &= ~(1 << (pos % 64)); } 19 | inline void flip_bit(int pos) { s[pos] ^= 1; } 20 | inline bool read_bit(int pos) { return bool(s[pos]); } 21 | inline void set_0() { memset(s, 0, sizeof(uint8_t) * size); } 22 | // inline int count() { int ans = 0; for(int i = 0; i < size; i++) ans += __builtin_popcountll(s[i]); return ans; } 23 | }; 24 | 25 | class VertexSet 26 | { 27 | public: 28 | VertexSet(); 29 | // allocate new memory according to max_intersection_size 30 | void init(); 31 | // use memory from Graph, do not allocate new memory 32 | void init(int input_size, int* input_data); 33 | void init_bs(Bitmap* bs, int input_size, int* input_data); 34 | void copy(int input_size, int* input_data); 35 | ~VertexSet(); 36 | void intersection(const VertexSet& set0, const VertexSet& set1, int min_vertex = -1, bool clique = false); 37 | void intersection_bs(const VertexSet& set0, Bitmap *bs, int *input_data, int input_size, int depth) ; 38 | 39 | void intersection_with(const VertexSet& set1); 40 | void intersection_bs_only_size(const VertexSet& set0, Bitmap *bs, const VertexSet& set1, int depth); 41 | 42 | //set1 is unordered 43 | static int unordered_subtraction_size(const VertexSet& set0, const VertexSet& set1, int size_after_restrict = -1); 44 | void insert_ans_sort(int val); 45 | inline void set_size(int _size) { size = _size; } 46 | inline int get_size() const { return size;} 47 | inline int get_data(int i) const { return data[i];} 48 | inline const int* get_data_ptr() const { return data;} 49 | inline int* get_data_ptr() { return data;} 50 | inline void push_back(int val) { data[size++] = val;} 51 | inline void pop_back() { --size;} 52 | inline int get_last() const { return data[size - 1];} 53 | bool has_data(int val); 54 | static int max_intersection_size; 55 | void build_vertex_set(const Schedule_IEP& schedule, const VertexSet* vertex_set, int* input_data, int input_size, int prefix_id, int min_vertex = -1, bool clique = false); 56 | void build_vertex_set_bs(const Schedule_IEP& schedule, const VertexSet* vertex_set, Bitmap *bs, int* input_data, int input_size, int prefix_id, int depth); 57 | void build_vertex_set_bs_only_size(const Schedule_IEP& schedule, const VertexSet* vertex_set, Bitmap *bs, int* input_data, int input_size, int prefix_id, int depth); 58 | private: 59 | int* data; 60 | int size; 61 | bool allocate; 62 | }; 63 | -------------------------------------------------------------------------------- /reproduce/clique_counting.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from utils import * 4 | from settings import * 5 | 6 | clique_graphs = ["patents", "mico", "livejournal", "orkut", "friendster"] 7 | clique_sizes = [4, 5] 8 | 9 | 10 | def clique_counting( 11 | is_gpu: bool = False, 12 | bin_path: str = "../build/bin", 13 | log_path: str = "../reproduce_log/clique_counting", 14 | result_path: str = "../reproduce_result", 15 | ): 16 | log_path = log_path + ("_gpu" if is_gpu else "_cpu") 17 | if not os.path.exists(log_path): 18 | os.makedirs(log_path) 19 | 20 | result_path = result_path 21 | if not os.path.exists(result_path): 22 | os.makedirs(result_path) 23 | result_path = ( 24 | f"{result_path}/clique_counting" + ("_gpu" if is_gpu else "_cpu") + ".csv" 25 | ) 26 | 27 | execute_name = "gpu_kclique" if is_gpu else "clique_test" 28 | 29 | data = [] 30 | data.append(["Size"] + clique_graphs) 31 | 32 | for size in clique_sizes: 33 | tmp = [size] 34 | for graph in clique_graphs: 35 | log_name = f"{log_path}/{graph}_cc{size}.log" 36 | command = f"{bin_path}/{execute_name} {DATA_PATH}/{graph}.g {size} 1>{log_name}" 37 | print(command, flush=True) 38 | result = os.system(COMMAND_PREFIX + command) 39 | tmp.append(read_time_cost(log_name)) 40 | if result != 0: 41 | return 1 42 | data.append(tmp) 43 | write_table(data, result_path) 44 | return 0 45 | 46 | if __name__ == "__main__": 47 | print("Reproducing clique counting results. (Time: 20 minutes)") 48 | print("Reproducing clique counting results on CPU...") 49 | assert clique_counting(is_gpu=False) == 0 50 | print("Reproducing clique counting results on GPU...") 51 | assert clique_counting(is_gpu=True) == 0 52 | print("Reproducing clique counting results done.") 53 | -------------------------------------------------------------------------------- /reproduce/frequent_subgraph_mining.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from settings import * 4 | from utils import * 5 | 6 | fsm_graphs = ['mico', 'patents', 'youtube'] 7 | fsm_pairs = [ 8 | [ # mico 9 | (2, [100, 300, 500]), 10 | (3, [10000, 13000, 15000]), 11 | ], 12 | [ # patents 13 | (2, [5000, 10000, 15000]), 14 | (3, [10000, 15000, 20000]) 15 | ], 16 | [ # youtube 17 | (2, [1000, 3000, 5000]), 18 | (3, [1000, 3000, 5000]) 19 | ] 20 | ] 21 | 22 | def frequent_subgraph_mining( 23 | is_gpu: bool = False, 24 | bin_path: str = "../build/bin", 25 | log_path: str = "../reproduce_log/frequent_subgraph_mining", 26 | result_path: str = "../reproduce_result", 27 | ): 28 | log_path = log_path + ("_gpu" if is_gpu else "_cpu") 29 | if not os.path.exists(log_path): 30 | os.makedirs(log_path) 31 | 32 | result_path = result_path 33 | if not os.path.exists(result_path): 34 | os.makedirs(result_path) 35 | result_path = ( 36 | f"{result_path}/frequent_subgraph_mining" 37 | + ("_gpu" if is_gpu else "_cpu") 38 | + ".csv" 39 | ) 40 | 41 | execute_name = "gpu_fsm" if is_gpu else "fsm_test" 42 | 43 | data = [] 44 | data.append(["size-support"] + fsm_graphs) 45 | 46 | size_support_list = [] 47 | 48 | for graph_index in range(len(fsm_graphs)): 49 | graph = fsm_graphs[graph_index] 50 | for fsm_data in fsm_pairs[graph_index]: 51 | size = fsm_data[0] 52 | for support in fsm_data[1]: 53 | size_support_list.append(f"{size}-{support}") 54 | 55 | size_support_list = list(set(size_support_list)) 56 | 57 | size_support_list.sort() 58 | 59 | tmp_data = [ 60 | [size_support] + [0] * (len(data[0]) - 1) for size_support in size_support_list 61 | ] 62 | 63 | for graph_index in range(len(fsm_graphs)): 64 | graph = fsm_graphs[graph_index] 65 | for fsm_data in fsm_pairs[graph_index]: 66 | size = fsm_data[0] 67 | for support in fsm_data[1]: 68 | tmp_execute_name = execute_name 69 | if graph == "mico" and size == 3: 70 | tmp_execute_name = "gpu_new_fsm" if is_gpu else "fsm_vertex_test" 71 | log_name = f"{log_path}/{graph}_fsm{size}+{support}.log" 72 | command = f"{bin_path}/{tmp_execute_name} {DATA_PATH}/{graph}.adj {size} {support} 1>{log_name}" 73 | print(command, flush=True) 74 | result = os.system(COMMAND_PREFIX + command) 75 | tmp_data[size_support_list.index(f"{size}-{support}")][ 76 | data[0].index(graph) 77 | ] = read_time_cost(log_name) 78 | if result != 0: 79 | return 1 80 | data += tmp_data 81 | write_table(data, result_path) 82 | return 0 83 | 84 | 85 | if __name__ == "__main__": 86 | print("Reproducing frequent subgraph mining results. (Time: 7 hours)") 87 | print("Reproducing frequent subgraph mining results on CPU...") 88 | assert frequent_subgraph_mining(is_gpu=False) == 0 89 | print("Reproducing frequent subgraph mining results on GPU...") 90 | assert frequent_subgraph_mining(is_gpu=True) == 0 91 | print("Reproducing frequent subgraph mining results done.") -------------------------------------------------------------------------------- /reproduce/gsi_cuts.py: -------------------------------------------------------------------------------- 1 | import os 2 | import math 3 | import matplotlib.pyplot as plt 4 | 5 | from settings import * 6 | from utils import * 7 | 8 | 9 | PATTERNS = [ 10 | "0111100111110011110111110", 11 | "0111010111110101110111110", 12 | "0110110111110111110011110", 13 | "0111010111110111100101110", 14 | "0011110110110011110111110", 15 | "0111010111010111110101110", 16 | "0101110111110011110011110", 17 | "0111110111100101110110110", 18 | "0111110111100110100111110", 19 | "0001110110110110110111110", 20 | "0111110100100111110111010", 21 | "001101100111110101111011111101111010", 22 | "010111100111110110111011111100111100", 23 | "011011101100110111111011101101011110", 24 | "011111001001010111111011111001011110", 25 | "010110001101110111111011111001110110", 26 | "010011001111100101111011111101101110", 27 | "010111101111100111111001011100111010", 28 | "011111100101110011111011101101011100", 29 | "011111101011100000111011111001111100", 30 | "010011101111100111111010110101100110", 31 | "000111101011110111001010111101111010", 32 | "0101110100111101010111110111011101111011011110010", 33 | "0110101101111011011111110011111101111111000110000", 34 | "0011111000111010011011110111101101101111010011110", 35 | "0101110100101111001110110011011101111111001110110", 36 | "0110011101001111011111110110011101101111010010110", 37 | "0110111100111111011110000101100101111101001111110", 38 | "0111011101111111001111010110011101011100010011110", 39 | "0101111101111100000111000111011101101111000111110", 40 | "0111011100111111011111000111101100101001011110100", 41 | "0110010100111101011111000011111101101110011111010", 42 | "0111111101111011000111010111011100010100010111110" 43 | ] 44 | 45 | GRAPHS = ["Enron", "gowalla", "roadNetCa", "roadNetPa", "roadNetTx", "wikiTalk"] 46 | 47 | 48 | def pattern_matching_gsi_cuts( 49 | is_gpu: bool = False, 50 | bin_path: str = "../build/bin", 51 | log_path: str = "../reproduce_log/pattern_matching_gsi_cuts", 52 | result_path: str = "../reproduce_result", 53 | ): 54 | log_path = log_path + ("_gpu" if is_gpu else "_cpu") 55 | 56 | if not os.path.exists(log_path): 57 | os.makedirs(log_path) 58 | 59 | result_path = result_path 60 | if not os.path.exists(result_path): 61 | os.makedirs(result_path) 62 | result_path = ( 63 | f"{result_path}/pattern_matching_gsi_cuts" + ("_gpu" if is_gpu else "_cpu") + ".csv" 64 | ) 65 | 66 | data = [] 67 | data.append(["Pattern"] + GRAPHS) 68 | 69 | execute_name = "gpu_graph" if is_gpu else "pm_test" 70 | 71 | for p in range(len(PATTERNS)): 72 | tmp = [f"p{p+1}"] 73 | for graph in GRAPHS: 74 | 75 | log_name = f"{log_path}/{graph}_p{p + 1}.log" 76 | command = f"{bin_path}/{execute_name} {DATA_PATH}/{graph}.g {int(math.sqrt(len(PATTERNS[p])))} {PATTERNS[p]} 0 1>{log_name}" 77 | print(command, flush=True) 78 | result = os.system(COMMAND_PREFIX + command) 79 | tmp.append(read_time_cost(log_name)) 80 | if result != 0: 81 | return 1 82 | data.append(tmp) 83 | write_table(data, result_path) 84 | return 0 85 | 86 | 87 | if __name__ == "__main__": 88 | print("Pattern Matching comparing GSI cuTS with GPU (Time: 5 hour)") 89 | pattern_matching_gsi_cuts(is_gpu=True) 90 | print("Done!") -------------------------------------------------------------------------------- /reproduce/motif_counting.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from utils import * 4 | from settings import * 5 | 6 | GRAPHS = ["mico", "patents", "orkut", "livejournal"] 7 | 8 | motif_sizes = [4] 9 | 10 | 11 | def motif_counting( 12 | is_gpu: bool = False, 13 | bin_path: str = "../build/bin", 14 | log_path: str = "../reproduce_log/motif_counting", 15 | result_path: str = "../reproduce_result", 16 | ): 17 | log_path = log_path + ("_gpu" if is_gpu else "_cpu") 18 | if not os.path.exists(log_path): 19 | os.makedirs(log_path) 20 | 21 | result_path = result_path 22 | if not os.path.exists(result_path): 23 | os.makedirs(result_path) 24 | result_path = ( 25 | f"{result_path}/motif_counting" + ("_gpu" if is_gpu else "_cpu") + ".csv" 26 | ) 27 | 28 | data = [] 29 | data.append(["Size"] + GRAPHS) 30 | 31 | execute_name = "gpu_mc" if is_gpu else "motif_counting_test" 32 | 33 | for size in motif_sizes: 34 | tmp = [size] 35 | for graph in GRAPHS: 36 | log_name = f"{log_path}/{graph}_mc{size}.log" 37 | command = f"{bin_path}/{execute_name} {DATA_PATH}/{graph}.g {size} 1>{log_name}" 38 | print(command, flush=True) 39 | result = os.system(COMMAND_PREFIX + command) 40 | tmp.append(read_time_cost(log_name)) 41 | if result != 0: 42 | return 1 43 | data.append(tmp) 44 | write_table(data, result_path) 45 | return 0 46 | 47 | if __name__ == "__main__": 48 | print("Reproducing motif counting results. (Time: 6 hours)") 49 | print("Reproducing motif counting results on CPU...") 50 | assert motif_counting(is_gpu=False) == 0 51 | print("Reproducing motif counting results on GPU...") 52 | assert motif_counting(is_gpu=True) == 0 53 | print("Reproducing motif counting results done.") 54 | -------------------------------------------------------------------------------- /reproduce/pattern_matching.py: -------------------------------------------------------------------------------- 1 | import os 2 | import math 3 | import matplotlib.pyplot as plt 4 | 5 | from settings import * 6 | from utils import * 7 | 8 | PATTERNS = [] 9 | PATTERNS.append("0111010011100011100001100") # p1 10 | PATTERNS.append("011011101110110101011000110000101000") # p2 11 | PATTERNS.append("011111101000110111101010101101101010") # p3 12 | PATTERNS.append("011110101101110000110000100001010010") # p4 13 | PATTERNS.append("0111111101111111011101110100111100011100001100000") # p5 14 | PATTERNS.append("0111111101111111011001110100111100011000001100000") # p6 15 | PATTERN_SIZES = [5, 6, 6, 6, 7, 7] 16 | 17 | GRAPHS = ["mico", "patents", "orkut", "livejournal"] 18 | 19 | 20 | def pattern_matching( 21 | is_gpu: bool = False, 22 | is_generated_code: bool = False, 23 | bin_path: str = "../build/bin", 24 | log_path: str = "../reproduce_log/pattern_matching", 25 | result_path: str = "../reproduce_result", 26 | ): 27 | log_path = log_path + ("_gpu" if is_gpu else "_cpu") 28 | if is_generated_code: 29 | log_path += "_generated" 30 | 31 | if not os.path.exists(log_path): 32 | os.makedirs(log_path) 33 | 34 | result_path = result_path 35 | if not os.path.exists(result_path): 36 | os.makedirs(result_path) 37 | result_path = ( 38 | f"{result_path}/pattern_matching" + ("_gpu" if is_gpu else "_cpu") + ".csv" 39 | ) 40 | 41 | data = [] 42 | data.append(["Pattern"] + GRAPHS) 43 | 44 | execute_name = "gpu_graph" if is_gpu else "pm_test" 45 | 46 | for p in range(len(PATTERNS)): 47 | tmp = [f"p{p+1}"] 48 | for graph in GRAPHS: 49 | if is_generated_code: 50 | execute_name = f"{graph}_p{p + 1}" 51 | log_name = f"{log_path}/{graph}_p{p + 1}.log" 52 | command = f"{bin_path}/{execute_name} {DATA_PATH}/{graph}.g {PATTERN_SIZES[p]} {PATTERNS[p]} 1>{log_name}" 53 | print(command, flush=True) 54 | result = os.system(COMMAND_PREFIX + command) 55 | tmp.append(read_time_cost(log_name)) 56 | if result != 0: 57 | return 1 58 | data.append(tmp) 59 | write_table(data, result_path) 60 | return 0 61 | 62 | def draw_pattern_matching(is_gpu: bool = False, result_path: str = "../reproduce_result"): 63 | with open(f"{result_path}/pattern_matching" + ("_gpu" if is_gpu else "_cpu") + ".csv", newline='') as csvfile: 64 | reader = csv.reader(csvfile) 65 | # first line is header: Pattern, [graph_names] 66 | header = next(reader) 67 | graph_names = header[1:] 68 | # other lines are data 69 | data = [] 70 | for row in reader: 71 | data.append(row) 72 | # transpose data 73 | data = list(map(list, zip(*data))) 74 | # first column is pattern names 75 | pattern_names = data[0] 76 | # other columns are time costs 77 | time_costs = data[1:] 78 | # draw a figure for every graph, and make them in one table horizontally 79 | fig_size = (3 * len(graph_names), 5) 80 | fig, axes = plt.subplots(1, len(graph_names), figsize=fig_size) 81 | for i in range(len(graph_names)): 82 | data_y = list(map(float, time_costs[i])) 83 | print(data_y) 84 | axes[i].set_title(graph_names[i]) 85 | axes[i].set_xlabel("Pattern") 86 | axes[i].set_ylabel("Time Cost (s)") 87 | axes[i].bar(pattern_names, data_y) 88 | # set y axis to log scale 89 | axes[i].set_yscale("log") 90 | # set y axis start to the minimum 10 powers smaller than the minimum time cost 91 | axes[i].set_ylim(bottom=10 ** (int(math.log10(min(data_y))) - 1)) 92 | plt.tight_layout() 93 | # add a name 94 | plt.suptitle("Pattern Matching" + (" (GPU)" if is_gpu else " (CPU)")) 95 | plt.savefig(f"{result_path}/pattern_matching" + ("_gpu" if is_gpu else "_cpu") + ".png") 96 | 97 | 98 | 99 | if __name__ == "__main__": 100 | print("Start reproducing pattern matching...(Total Estimated Time Cost: 7 hours)") 101 | print("Reproducing pattern matching on GPU...") 102 | assert pattern_matching(is_gpu=True, is_generated_code=True) == 0 103 | draw_pattern_matching(is_gpu=True) 104 | print("Reproducing pattern matching on CPU...") 105 | assert pattern_matching(is_gpu=False) == 0 106 | draw_pattern_matching(is_gpu=False) 107 | print("Finish reproducing pattern matching!") 108 | -------------------------------------------------------------------------------- /reproduce/scalability.py: -------------------------------------------------------------------------------- 1 | import os 2 | import math 3 | import matplotlib.pyplot as plt 4 | 5 | from settings import * 6 | from utils import * 7 | 8 | PATTERNS = [] 9 | PATTERNS.append("0111010011100011100001100") # p3 10 | PATTERNS.append("011011101110110101011000110000101000") # p4 11 | PATTERNS.append("011111101000110111101010101101101010") # p5 12 | PATTERNS.append("011110101101110000110000100001010010") # p6 13 | PATTERNS.append("0111111101111111011101110100111100011100001100000") # p7 14 | PATTERNS.append("0111111101111111011001110100111100011000001100000") # p8 15 | PATTERNS.append("011101110") # p1 16 | PATTERNS.append("0111101111011110") # p2 17 | 18 | GRAPH = "livejournal" 19 | 20 | 21 | GPU_CARDS = [1, 2, 4, 8] 22 | 23 | def pattern_matching_scalability( 24 | is_gpu: bool = False, 25 | bin_path: str = "../build/bin", 26 | log_path: str = "../reproduce_log/pattern_matching_scalability", 27 | result_path: str = "../reproduce_result", 28 | ): 29 | if not is_gpu: 30 | return NotImplementedError 31 | log_path = log_path + ("_gpu" if is_gpu else "_cpu") 32 | 33 | if not os.path.exists(log_path): 34 | os.makedirs(log_path) 35 | 36 | result_path = result_path 37 | if not os.path.exists(result_path): 38 | os.makedirs(result_path) 39 | result_path = ( 40 | f"{result_path}/pattern_matching_scalability" + ("_gpu" if is_gpu else "_cpu") + ".csv" 41 | ) 42 | 43 | data = [] 44 | data.append(["Cards"] + GPU_CARDS) 45 | 46 | execute_name = "gpu_graph_static_task" if is_gpu else "pm_test" 47 | 48 | for p in range(len(PATTERNS)): 49 | tmp = [f"p{p+1}"] 50 | for n in range(len(GPU_CARDS)): 51 | log_name = f"{log_path}/{GRAPH}_p{p + 1}_n{GPU_CARDS[n]}.log" 52 | command = f"{bin_path}/{execute_name} {DATA_PATH}/{GRAPH}.g 0 {PATTERNS[p]} {GPU_CARDS[n]} 1>{log_name}" 53 | print(command, flush=True) 54 | result = os.system(MULTI_CARD_COMMAND_PREFIX + command) 55 | tmp.append(read_time_cost(log_name)) 56 | if result != 0: 57 | return 1 58 | data.append(tmp) 59 | write_table(data, result_path) 60 | return 0 61 | 62 | def draw_pattern_matching_scalability(is_gpu: bool = False, result_path: str = "../reproduce_result"): 63 | if not is_gpu: 64 | return NotImplementedError 65 | with open(f"{result_path}/pattern_matching_scalability" + ("_gpu" if is_gpu else "_cpu") + ".csv", newline='') as csvfile: 66 | reader = csv.reader(csvfile) 67 | # first line is header: Pattern, [graph_names] 68 | header = next(reader) 69 | # other lines are data 70 | data = [] 71 | for row in reader: 72 | data.append(row) 73 | 74 | # first column is pattern names 75 | pattern_names = [data[i][0] for i in range(0, len(data))] 76 | 77 | # other columns are time costs 78 | time_costs = [data[i][1:] for i in range(0, len(data))] 79 | print(time_costs) 80 | # draw a line graph consisting of the acceleration of each pattern 81 | for i in range(len(PATTERNS)): 82 | # convert string to float 83 | time_costs[i] = list(map(float, time_costs[i])) 84 | # calculate acceleration 85 | time_costs[i] = [time_costs[i][0] / time_costs[i][j] for j in range(len(time_costs[i]))] 86 | print(time_costs) 87 | # draw 88 | plt.figure(figsize=(8, 8)) 89 | plt.title("Pattern Matching Scalability" + (" (GPU)" if is_gpu else " (CPU)")) 90 | plt.xlabel("Cards") 91 | plt.ylabel("Acceleration") 92 | for i in range(len(pattern_names)): 93 | plt.plot(GPU_CARDS, time_costs[i], label=pattern_names[i], marker='o') 94 | # set x axis to log scale base 2 95 | plt.loglog(base=2) 96 | plt.legend() 97 | plt.savefig(f"{result_path}/pattern_matching_scalability" + ("_gpu" if is_gpu else "_cpu") + ".png") 98 | 99 | 100 | 101 | 102 | 103 | if __name__ == "__main__": 104 | print("Reproducing pattern matching scalability on GPU... (Expected time cost: 1 hour) ") 105 | assert pattern_matching_scalability(is_gpu=True) == 0 106 | draw_pattern_matching_scalability(is_gpu=True) 107 | print("Finished.") 108 | -------------------------------------------------------------------------------- /reproduce/settings.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | # modify that to your own path 4 | DATA_PATH = "/home/cqq/data" 5 | 6 | # modify that to your own path 7 | COMMAND_PREFIX = "srun -p V100 --gres=gpu:v132p:1 --exclusive " 8 | 9 | 10 | MULTI_CARD_COMMAND_PREFIX = "srun -p V100 -n 1 --exclusive " -------------------------------------------------------------------------------- /reproduce/utils.py: -------------------------------------------------------------------------------- 1 | import re 2 | import csv 3 | 4 | def read_time_cost(file_path): 5 | with open(file_path, 'r') as file: 6 | content = file.read() 7 | pattern = r"Counting time cost: (\d+\.\d+) s" 8 | match = re.search(pattern, content) 9 | 10 | if match: 11 | time_cost = float(match.group(1)) 12 | return time_cost 13 | else: 14 | print(f"Time not found in file {file_path}.") 15 | return None 16 | 17 | def write_table(table, csv_file): 18 | # Write table and header into a CSV file 19 | with open(csv_file, 'w', newline='') as csvfile: 20 | writer = csv.writer(csvfile) 21 | writer.writerows(table) 22 | 23 | -------------------------------------------------------------------------------- /scripts/analyze.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | if 0: # 输入格式:@warp_id,time_begin,time_end 4 | with open('timing.txt', 'r') as f: 5 | lines = f.readlines() 6 | 7 | records = [] 8 | for line in lines: 9 | if line.startswith('@'): 10 | records.append(line[1:].strip().split(',')) 11 | 12 | warp_ids = set([int(r[0]) for r in records]) 13 | print("number of warps: %d" % len(warp_ids)) 14 | ''' 15 | time_points = [] 16 | for r in records: 17 | time_points.append(int(r[1])) 18 | time_points.append(int(r[2])) 19 | time_points = sorted(time_points) 20 | 21 | unique_time_points = [time_points[0]] 22 | for i in range(1, len(time_points)): 23 | if time_points[i] != time_points[i - 1]: 24 | unique_time_points.append(time_points[i]) 25 | 26 | max_timestamp = unique_time_points[-1] 27 | nr_intervals = 10000 28 | interval_len = (max_timestamp + nr_intervals - 1) // nr_intervals 29 | active_warps_count = [0.0] * nr_intervals 30 | for r in records: 31 | t1, t2 = int(r[1]), int(r[2]) 32 | 33 | left = t1 // interval_len 34 | right = (t2 + interval_len - 1) // interval_len 35 | for i in range(left, right): 36 | begin = interval_len * i 37 | end = begin + interval_len 38 | active_warps_count[i] += (min(end, t2) - max(begin, t1)) / interval_len 39 | ''' 40 | total_time_costs = {} 41 | num_tasks = {} 42 | time_costs = [] 43 | for r in records: 44 | warp_id, t1, t2 = int(r[0]), int(r[1]), int(r[2]) 45 | time_costs.append(t2 - t1) 46 | # 47 | tot = total_time_costs.get(warp_id, 0) 48 | tot += t2 - t1 49 | total_time_costs[warp_id] = tot 50 | # 51 | num_tasks[warp_id] = num_tasks.get(warp_id, 0) + 1 52 | 53 | with open('time_costs.json', 'w') as f: 54 | json.dump({'task_time': time_costs, 'total_time': total_time_costs, 'num_tasks': num_tasks}, f) 55 | 56 | if __name__ == '__main__': 57 | # 输入格式:@smid:end_time 58 | with open('timing.txt', 'r') as f: 59 | lines = f.readlines() 60 | 61 | data = [] 62 | timestamps = [] 63 | for line in lines: 64 | if not line.startswith('@'): 65 | continue 66 | r = line[1:].strip().split(':') 67 | data.append(tuple(map(int, r))) 68 | timestamps.append(int(r[1])) 69 | 70 | min_time = min(timestamps) 71 | timestamps = [t - min_time for t in timestamps] 72 | print(timestamps) 73 | 74 | from IPython import embed 75 | #embed() -------------------------------------------------------------------------------- /scripts/check.py: -------------------------------------------------------------------------------- 1 | from IPython import embed 2 | from operator import itemgetter 3 | 4 | def parse_kv(line, sep=':'): 5 | ls = line[1:].split(sep) 6 | return int(ls[0]), int(ls[1]) 7 | 8 | def check(): 9 | with open('32.txt', 'r') as f: 10 | raw_lines1 = f.readlines() 11 | with open('64.txt', 'r') as f: 12 | raw_lines2 = f.readlines() 13 | 14 | lines1 = [line for line in raw_lines1 if line[0] == '#'] 15 | lines2 = [line for line in raw_lines2 if line[0] == '#'] 16 | 17 | es1 = dict(parse_kv(line) for line in lines1) 18 | es2 = dict(parse_kv(line) for line in lines2) 19 | 20 | assert(es1.keys() == es2.keys()) 21 | 22 | outputs = [] 23 | for k in es1.keys(): 24 | v1, v2 = es1[k], es2[k] 25 | if v1 != v2: 26 | line = 'i: %d v1: %d v2: %d\n' % (k, v1, v2) 27 | outputs.append(line) 28 | 29 | txt = ''.join(outputs) 30 | with open('diff.txt', 'w') as f: 31 | f.write(txt) 32 | 33 | def sort_data(): 34 | with open('8.txt', 'r') as f: 35 | raw_lines = f.readlines() 36 | 37 | values = [tuple(map(int, line[1:].split(','))) for line in raw_lines if line[0] == '$'] 38 | values.sort() 39 | for v in values: 40 | print('block %d edge %d thread %d val %d' % (v[0], v[1], v[2], v[3])) 41 | 42 | if __name__ == '__main__': 43 | check() 44 | -------------------------------------------------------------------------------- /scripts/fsm_test.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def main(): 4 | min_support = [x for x in range(30000, 0, -1000)] + [x for x in range(1000, 100, -100)] 5 | max_edges = [2, 3] 6 | graphs = [] 7 | graphs.append("patents.adj") 8 | graphs.append("youtube.adj") 9 | graphs.append("mico.adj") 10 | g = [] 11 | g.append("pt") 12 | g.append("yt") 13 | g.append("mc") 14 | for g_idx, graph in enumerate(graphs): 15 | for b in min_support: 16 | for a in max_edges: 17 | bin_name = "fsm_test" 18 | log_name = g[g_idx] + "_" + str(a) + "fsm_" + str(b) + ".log" 19 | command = "OMP_PROC_BIND=true ./bin/" + bin_name + " /home/cqq/data/" + graph + " " + str(a) + " " + str(b) + " > " + log_name 20 | print(command) 21 | if(os.system(command)): 22 | return 23 | 24 | if __name__ == "__main__": 25 | main() -------------------------------------------------------------------------------- /scripts/gen_code.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | data_path = "/home/cqq/data" 4 | file_dir = os.path.dirname(__file__) 5 | 6 | command_prefix = "srun -p V100 --gres=gpu:v132p:1 --exclusive " 7 | 8 | patterns = [] 9 | patterns.append("0111010011100011100001100") # p1 10 | patterns.append("011011101110110101011000110000101000") # p2 11 | patterns.append("011111101000110111101010101101101010") # p3 12 | patterns.append("011110101101110000110000100001010010") # p4 13 | patterns.append("0111111101111111011101110100111100011100001100000") # p5 14 | patterns.append("0111111101111111011001110100111100011000001100000") # p6 15 | 16 | pattern_sizes = [5, 6, 6, 6, 7, 7] 17 | graphs = [] 18 | graphs.append("patents") 19 | graphs.append("mico") 20 | graphs.append("livejournal") 21 | graphs.append("orkut") 22 | 23 | 24 | for g_idx, graph in enumerate(graphs): 25 | for p in range(len(patterns)): 26 | output_name = f"{file_dir}/../auto/{graph}_p{p+1}.cu" 27 | commands = f"{file_dir}/../build/bin/final_generator {data_path}/{graph}.g {pattern_sizes[p]} {patterns[p]} > {output_name}" 28 | print(commands, flush=True) 29 | os.system(command_prefix + commands) 30 | os.system(f"cd {file_dir}/../auto; bash concat.sh") -------------------------------------------------------------------------------- /scripts/generate.py: -------------------------------------------------------------------------------- 1 | ''' 2 | 用于生成完全图 3 | ''' 4 | if __name__ == '__main__': 5 | n = 128 6 | m = n * (n - 1) // 2 7 | txt = '%d %d\n' % (n, m) 8 | for i in range(n): 9 | for j in range(i + 1, n): 10 | txt += '%d %d\n' % (i+1, j+1) 11 | with open('clique_input', 'w') as f: 12 | f.write(txt) 13 | -------------------------------------------------------------------------------- /scripts/run.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def main(): 4 | patterns = [] 5 | patterns.append("0111010011100011100001100") 6 | patterns.append("011011101110110101011000110000101000") 7 | patterns.append("011111101000110111101010101101101010") 8 | patterns.append("011110101101110000110000100001010010") 9 | patterns.append("0111111101111111011101110100111100011100001100000") 10 | patterns.append("0111111101111111011001110100111100011000001100000") 11 | pattern_sizes = [5, 6, 6, 6, 7, 7] 12 | graphs = [] 13 | graphs.append("patents") 14 | graphs.append("mico") 15 | graphs.append("livejournal") 16 | graphs.append("orkut") 17 | for graph in graphs: 18 | for p in range(len(patterns)): 19 | for node in [1, 2]: 20 | # for times in [1, 2, 3]: 21 | log_name = graph + "_" + "p" + str(p + 1) + "_" + str(node) + "node.log" 22 | command = "srun -N " + str(node) + " -p Big --exclusive ./bin/gpu_graph_static_task /home/cqq/data/" + graph + ".g " + str(pattern_sizes[p]) + " " + str(patterns[p]) + " > " + log_name + " 2>&1 &" 23 | print(command) 24 | result = os.system(command) 25 | if result != 0: 26 | return 27 | 28 | 29 | if __name__ == "__main__": 30 | main() -------------------------------------------------------------------------------- /scripts/run_generated_code.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | patterns = [] 4 | patterns.append("0111010011100011100001100") 5 | patterns.append("011011101110110101011000110000101000") 6 | patterns.append("011111101000110111101010101101101010") 7 | patterns.append("011110101101110000110000100001010010") 8 | patterns.append("0111111101111111011101110100111100011100001100000") 9 | patterns.append("0111111101111111011001110100111100011000001100000") 10 | pattern_sizes = [5, 6, 6, 6, 7, 7] 11 | graphs = [] 12 | graphs.append("patents.g") 13 | graphs.append("mico.g") 14 | graphs.append("livejournal.g") 15 | graphs.append("orkut.g") 16 | g = [] 17 | g.append('wv') 18 | g.append("pt") 19 | g.append("mc") 20 | g.append("lj") 21 | g.append("or") 22 | for g_idx, graph in enumerate(graphs): 23 | for p in range(len(patterns)): 24 | bin_name = g[g_idx] + "_p" + str(p + 1) 25 | log_name = graph + "_" + "p" + str(p + 1) + ".log" 26 | #log_name = "../auto/" + g[g_idx] + "_p" + str(p + 1) + "_inject.cu" 27 | os.system("./bin/" + bin_name + " /home/cqq/data/" + graph + " " + str(pattern_sizes[p]) + " " + str(patterns[p]) + " > " + log_name + " ") -------------------------------------------------------------------------------- /scripts/runprof.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | << comment 3 | comments 4 | comment 5 | 6 | all_metrics="inst_per_warp,branch_efficiency,warp_execution_efficiency,warp_nonpred_execution_efficiency,inst_replay_overhead,shared_load_transactions_per_request,shared_store_transactions_per_request,local_load_transactions_per_request,local_store_transactions_per_request,gld_transactions_per_request,gst_transactions_per_request,shared_store_transactions,shared_load_transactions,local_load_transactions,local_store_transactions,gld_transactions,gst_transactions,sysmem_read_transactions,sysmem_write_transactions,l2_read_transactions,l2_write_transactions,dram_read_transactions,dram_write_transactions,global_hit_rate,local_hit_rate,gld_requested_throughput,gst_requested_throughput,gld_throughput,gst_throughput,local_memory_overhead,tex_cache_hit_rate,l2_tex_read_hit_rate,l2_tex_write_hit_rate,dram_read_throughput,dram_write_throughput,tex_cache_throughput,l2_tex_read_throughput,l2_tex_write_throughput,l2_read_throughput,l2_write_throughput,sysmem_read_throughput,sysmem_write_throughput,local_load_throughput,local_store_throughput,shared_load_throughput,shared_store_throughput,gld_efficiency,gst_efficiency,tex_cache_transactions,flop_count_dp,flop_count_dp_add,flop_count_dp_fma,flop_count_dp_mul,flop_count_sp,flop_count_sp_add,flop_count_sp_fma,flop_count_sp_mul,flop_count_sp_special,inst_executed,inst_issued,dram_utilization,sysmem_utilization,stall_inst_fetch,stall_exec_dependency,stall_memory_dependency,stall_texture,stall_sync,stall_other,stall_constant_memory_dependency,stall_pipe_busy,shared_efficiency,inst_fp_32,inst_fp_64,inst_integer,inst_bit_convert,inst_control,inst_compute_ld_st,inst_misc,inst_inter_thread_communication,issue_slots,cf_issued,cf_executed,ldst_issued,ldst_executed,atomic_transactions,atomic_transactions_per_request,l2_atomic_throughput,l2_atomic_transactions,l2_tex_read_transactions,stall_memory_throttle,stall_not_selected,l2_tex_write_transactions,flop_count_hp,flop_count_hp_add,flop_count_hp_mul,flop_count_hp_fma,inst_fp_16,ipc,issued_ipc,issue_slot_utilization,sm_efficiency,achieved_occupancy,eligible_warps_per_cycle,shared_utilization,l2_utilization,tex_utilization,ldst_fu_utilization,cf_fu_utilization,tex_fu_utilization,special_fu_utilization,half_precision_fu_utilization,single_precision_fu_utilization,double_precision_fu_utilization,flop_hp_efficiency,flop_sp_efficiency,flop_dp_efficiency,sysmem_read_utilization,sysmem_write_utilization,stall_sleeping,pcie_total_data_transmitted,pcie_total_data_received,inst_executed_global_loads,inst_executed_local_loads,inst_executed_shared_loads,inst_executed_surface_loads,inst_executed_global_stores,inst_executed_local_stores,inst_executed_shared_stores,inst_executed_surface_stores,inst_executed_global_atomics,inst_executed_global_reductions,inst_executed_surface_atomics,inst_executed_surface_reductions,inst_executed_shared_atomics,inst_executed_tex_ops,dram_read_bytes,dram_write_bytes,global_load_requests,local_load_requests,surface_load_requests,global_store_requests,local_store_requests,surface_store_requests,global_atomic_requests,global_reduction_requests,surface_atomic_requests,surface_reduction_requests,l2_global_load_bytes,l2_local_load_bytes,l2_surface_load_bytes,l2_global_atomic_store_bytes,l2_local_global_store_bytes,l2_surface_store_bytes,sysmem_read_bytes,sysmem_write_bytes,l2_tex_hit_rate,texture_load_requests,tensor_precision_fu_utilization" 7 | metrics="inst_per_warp,warp_execution_efficiency,warp_nonpred_execution_efficiency,shared_efficiency,gld_throughput,gld_requested_throughput,sm_efficiency,eligible_warps_per_cycle,achieved_occupancy,ipc,tex_cache_hit_rate" 8 | 9 | nvprof --metrics ${metrics} bin/gpu_graph MiCo ~zms/mico_input 10 | nvprof --metrics ${metrics} bin/gpu_graph_old MiCo ~zms/mico_input 11 | -------------------------------------------------------------------------------- /scripts/runtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | << comment 3 | for i in {1..5}; do 4 | # echo $i 5 | echo "[baseline orkut]" >> output.txt 6 | bin/baseline_test Orkut ~zms/orkut_input | tee -a output.txt 7 | echo "[gpu_graph orkut]" >> output.txt 8 | ../../GraphMining-GPU/build/bin/gpu_graph Orkut ~zms/orkut_input | tee -a output.txt 9 | echo "[gpu_graph* orkut]" >> output.txt 10 | bin/gpu_graph Orkut ~zms/orkut_input | tee -a output.txt 11 | echo "[gpu_house orkut]" >> output.txt 12 | bin/gpu_house Orkut ~zms/orkut_input | tee -a output.txt 13 | done 14 | comment 15 | 16 | for i in {1..4}; do 17 | echo "[baseline livejournal]" >> output2.txt 18 | bin/baseline_test LiveJournal ~zms/livejournal_input | tee -a output2.txt 19 | echo "[gpu_graph livejournal]" >> output2.txt 20 | ../../GraphMining-GPU/build/bin/gpu_graph LiveJournal ~zms/livejournal_input | tee -a output2.txt 21 | echo "[gpu_graph* livejournal]" >> output2.txt 22 | bin/gpu_graph LiveJournal ~zms/livejournal_input | tee -a output2.txt 23 | echo "[gpu_house livejournal]" >> output2.txt 24 | bin/gpu_house LiveJournal ~zms/livejournal_input | tee -a output2.txt 25 | done -------------------------------------------------------------------------------- /scripts/small_graph_check.py: -------------------------------------------------------------------------------- 1 | # 寻找一个能复现bug的小图。 2 | # 如果pattern大小为N,则会先检查所有大小为N的图(共2^(N*(N-1)/2)种),再检查大小为N+1的图……直到找到发生错误 3 | # 由于原程序中输出的东西太多,需要先修改源程序,让其将答案输出至1.out和2.out,其余内容可以输出至stdout(本程序中不会做重定向) 4 | # 使用本程序,需要修改N、bin1和bin2,编译一个正确版本和有bug版本的 5 | # 由于我们的dataloader要求不能存在度数为0的点,所以很多生成的图是不合法的,如果报了“vertex number error!”是正常的 6 | 7 | import os 8 | 9 | N = 5 10 | bin1 = "../build/bin/gpu_graph" 11 | res1 = "1.out" 12 | bin2 = "../build/bin/gpu_graph_correct" 13 | res2 = "2.out" 14 | 15 | while (True): 16 | print("N = " + str(N)) 17 | print("range = ", range(2 ** int(N * (N - 1) / 2))) 18 | for i in range(2 ** int(N * (N - 1) / 2)): 19 | x = i 20 | e_num = 0 21 | while (x != 0): 22 | e_num += x & 1 23 | x >>= 1 24 | f = open("graph.out", "w") 25 | f.write(str(N) + " " + str(e_num) + "\n") 26 | x = i 27 | for j in range(1, N): 28 | for k in range(j + 1, N + 1): 29 | if (x & 1 == 1): 30 | f.write(str(j) + " " + str(k) + "\n") 31 | x >>= 1 32 | f.close() 33 | os.system("srun -N 1 " + bin1 + " Patents graph.out") 34 | os.system("srun -N 1 " + bin2 + " Patents graph.out") 35 | if os.path.exists(res1) and os.path.exists(res2) and os.system("diff -w -q " + res1 + " " + res2) != 0: 36 | break 37 | print("i = " + str(i) + " Correct.") 38 | N += 1 39 | -------------------------------------------------------------------------------- /scripts/txt2adj.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | if __name__ == '__main__': 5 | input_name = '/home/hzx/data/graphs/mico.txt' 6 | output_name = '/home/sth/download/GraphMining-GPU/mico.adj' 7 | 8 | with open(input_name, 'r') as f: 9 | lines = f.readlines() 10 | 11 | node2labels = {} 12 | v2real_v = {} #重编号,因为读入带label的图时默认节点编号从0到n-1 13 | real_v2v = {} 14 | edges = [] 15 | 16 | for line_id, line in enumerate(lines): 17 | tokens = line.strip().split() 18 | 19 | tp = tokens[0] 20 | if tp == 'v': 21 | v = int(tokens[1]) 22 | l = int(tokens[2]) 23 | real_v = len(v2real_v) 24 | if v in v2real_v: 25 | print("重复节点") 26 | sys.exit() 27 | v2real_v[v] = real_v 28 | real_v2v[real_v] = v 29 | node2labels[real_v] = l 30 | elif tp == 'e': 31 | u, v, l = int(tokens[1]), int(tokens[2]), int(tokens[3]) 32 | if not u in v2real_v or not v in v2real_v: 33 | print("节点不存在或还未被读入") 34 | sys.exit() 35 | if l != 0: 36 | print("目前仅支持边的label为0") 37 | sys.exit() 38 | u = v2real_v[u] 39 | v = v2real_v[v] 40 | edges.append((u, v)) 41 | elif tp == 't': 42 | if line_id != 0: 43 | print("输入文件包含不止一组数据") 44 | sys.exit() 45 | else: 46 | print("未知类型") 47 | print("line num = " + str(line_id)) 48 | sys.exit() 49 | 50 | 51 | print('|V| = %d |E| = %d' % (len(node2labels), len(edges))) 52 | 53 | new_edges = [] 54 | edges = sorted(edges) 55 | 56 | u, v = edges[0] 57 | if u != v: 58 | new_edges.append((u, v)) 59 | for i in range(len(edges) - 1): 60 | prev_edge = edges[i] 61 | cur_edge = edges[i + 1] 62 | if prev_edge != cur_edge: 63 | u, v = cur_edge 64 | if u != v: 65 | new_edges.append(cur_edge) 66 | 67 | print('边表去重并去自环后 |E| = %d' % len(new_edges)) 68 | 69 | adj = {} 70 | for u, v in new_edges: 71 | def add_edge(adj, u, v): 72 | if adj.get(u) is None: 73 | adj[u] = [] 74 | adj[u].append(v) 75 | 76 | add_edge(adj, u, v) 77 | add_edge(adj, v, u) 78 | 79 | #由于删除边后可能有0度的点,还需要删除这些点,对点重编号 80 | old_v_cnt = len(v2real_v) 81 | v2real_v = {} 82 | for v in range(old_v_cnt): 83 | if not adj.get(v) is None: 84 | real_v = len(v2real_v) 85 | v2real_v[v] = real_v 86 | 87 | print("删除0度点后 |V| = %d" % len(v2real_v)) 88 | 89 | with open(output_name, 'w') as f: 90 | def wl(s): 91 | f.write('%s\n' % s) 92 | def w(s): 93 | f.write(s) 94 | wl('%d' % (len(v2real_v))) 95 | 96 | adj_items = sorted(adj.items()) 97 | for u, neighbors in adj_items: 98 | w('%d %d' % (v2real_v[u], node2labels[u])) 99 | for v in neighbors: 100 | w(' %d' % (v2real_v[v])) 101 | w('\n') 102 | print("转换完成") 103 | 104 | -------------------------------------------------------------------------------- /spack-env.sh: -------------------------------------------------------------------------------- 1 | spack load cmake@3.18.4%gcc@10.2.1 2 | spack load cuda@11.3.0%gcc@10.2.1 3 | spack load mpi 4 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | SET(GraphMiningSrc 2 | graph.cpp 3 | labeled_graph.cpp 4 | dataloader.cpp 5 | pattern.cpp 6 | prefix.cpp 7 | #schedule.cpp 8 | schedule_IEP.cpp 9 | vertex_set.cpp 10 | motif_generator.cpp 11 | graphmpi.cpp 12 | common.cpp 13 | disjoint_set_union.cpp 14 | set_operation.cpp 15 | ) 16 | 17 | ADD_LIBRARY(graph_mining SHARED ${GraphMiningSrc}) 18 | 19 | ADD_EXECUTABLE(fsm_test fsm_test.cpp) 20 | TARGET_LINK_LIBRARIES(fsm_test graph_mining) 21 | 22 | ADD_EXECUTABLE(fsm_vertex_test fsm_vertex_test.cpp) 23 | TARGET_LINK_LIBRARIES(fsm_vertex_test graph_mining) 24 | 25 | ADD_EXECUTABLE(clique_test clique_test.cpp) 26 | TARGET_LINK_LIBRARIES(clique_test graph_mining) 27 | 28 | ADD_EXECUTABLE(motif_counting_test motif_counting_test.cpp) 29 | TARGET_LINK_LIBRARIES(motif_counting_test graph_mining) 30 | 31 | ADD_EXECUTABLE(pm_test pm_test.cpp) 32 | TARGET_LINK_LIBRARIES(pm_test graph_mining) 33 | 34 | #ADD_EXECUTABLE(in_exclusion_performance_test in_exclusion_performance_test.cpp) 35 | #TARGET_LINK_LIBRARIES(in_exclusion_performance_test graph_mining) 36 | 37 | #ADD_EXECUTABLE(performance_compare_test performance_compare_test.cpp) 38 | #TARGET_LINK_LIBRARIES(performance_compare_test graph_mining) 39 | 40 | #ADD_EXECUTABLE(schedule_printer schedule_printer.cpp) 41 | #TARGET_LINK_LIBRARIES(schedule_printer graph_mining) 42 | 43 | #ADD_EXECUTABLE(restricts_printer restricts_printer.cpp) 44 | #TARGET_LINK_LIBRARIES(restricts_printer graph_mining) 45 | 46 | #ADD_EXECUTABLE(run_brute_force_tc run_brute_force_tc.cpp) 47 | #TARGET_LINK_LIBRARIES(run_brute_force_tc graph_mining) 48 | 49 | #ADD_EXECUTABLE(run_general_tc run_general_tc.cpp) 50 | #TARGET_LINK_LIBRARIES(run_general_tc graph_mining) 51 | -------------------------------------------------------------------------------- /src/clique_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | #include "omp.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | double test_pattern(Graph* g, Pattern &pattern) { 15 | 16 | bool is_pattern_valid; 17 | int performance_modeling_type; 18 | bool use_in_exclusion_optimize; 19 | 20 | performance_modeling_type = 1; 21 | use_in_exclusion_optimize = true; 22 | Schedule_IEP schedule_our(pattern, is_pattern_valid, performance_modeling_type, 1, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 23 | assert(is_pattern_valid==true); 24 | 25 | double t1,t2; 26 | double total_time = 0; 27 | 28 | int times = 1; 29 | 30 | printf("thread num: %d\n", omp_get_max_threads()); 31 | 32 | for(int i = 0; i < times; ++i) { 33 | t1 = get_wall_time(); 34 | long long ans_our = g->pattern_matching(schedule_our, true); 35 | t2 = get_wall_time(); 36 | 37 | printf("ans: %lld time: %.6lf\n", ans_our, t2 - t1); 38 | total_time += (t2 - t1); 39 | if(i == times - 1) { 40 | schedule_our.print_schedule(); 41 | } 42 | fflush(stdout); 43 | } 44 | total_time /= times; 45 | printf("Counting time cost: %.6lf s\n",total_time); 46 | return total_time; 47 | } 48 | 49 | int main(int argc,char *argv[]) { 50 | Graph *g; 51 | DataLoader D; 52 | 53 | if(argc != 3) { 54 | printf("usage: %s graph_file clique_size\n", argv[0]); 55 | return 0; 56 | } 57 | 58 | DataType type = DataType::Patents; 59 | 60 | bool ok = D.fast_load(g, argv[1]); 61 | if(!ok) { printf("Load data failed\n"); return 0; } 62 | 63 | printf("Load data success!\n"); 64 | fflush(stdout); 65 | int size = atoi(argv[2]); 66 | Pattern pattern(size); 67 | for(int i = 0; i < size; i++) { 68 | for(int j = i + 1; j < size; j++) { 69 | pattern.add_edge(i, j); 70 | } 71 | } 72 | 73 | reduce_edges_for_clique(*g); 74 | test_pattern(g, pattern); 75 | delete g; 76 | return 0; 77 | } -------------------------------------------------------------------------------- /src/common.cpp: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | double get_wall_time() { 6 | struct timeval time; 7 | if(gettimeofday(&time,NULL)) { 8 | return 0; 9 | } 10 | return (double)time.tv_sec + (double)time.tv_usec * 0.000001; 11 | } 12 | 13 | void PatternType_printer(PatternType type) { 14 | if(type == PatternType::Rectangle) { 15 | printf("Rectangle\n"); 16 | } 17 | if(type == PatternType::Pentagon) { 18 | printf("Pentagon\n"); 19 | } 20 | if(type == PatternType::House) { 21 | printf("House\n"); 22 | } 23 | if(type == PatternType::Hourglass) { 24 | printf("Hourglass\n"); 25 | } 26 | if(type == PatternType::Cycle_6_Tri) { 27 | printf("Cycle_6_Tri\n"); 28 | } 29 | if(type == PatternType::Clique_7_Minus) { 30 | printf("Clique_7_Minus\n"); 31 | } 32 | } 33 | 34 | bool is_equal_adj_mat(const int* adj_mat1, const int* adj_mat2, int size) { 35 | for(int i = 0; i < size; ++i) 36 | for(int j = 0; j < size; ++j) 37 | if(adj_mat1[INDEX(i,j,size)] != adj_mat2[INDEX(i,j,size)]) 38 | return false; 39 | return true; 40 | } 41 | 42 | void GetDataType(DataType &type, const std::string str) { 43 | type = DataType::Invalid; 44 | 45 | if( str == "Patents" ) { 46 | type = DataType::Patents; 47 | } 48 | if(str == "Orkut" ) { 49 | type = DataType::Orkut; 50 | } 51 | if(str == "complete8" ) { 52 | type = DataType::complete8; 53 | } 54 | if(str == "LiveJournal" ) { 55 | type = DataType::LiveJournal; 56 | } 57 | if(str == "MiCo" ) { 58 | type = DataType::MiCo; 59 | } 60 | if(str == "Twitter" ) { 61 | type = DataType::Twitter; 62 | } 63 | if(str == "CiteSeer" ) { 64 | type = DataType::CiteSeer; 65 | } 66 | if(str == "Wiki-Vote" ) { 67 | type = DataType::Wiki_Vote; 68 | } 69 | if(str == "YouTube" ) { 70 | type = DataType::YouTube; 71 | } 72 | if(str == "Friendster" ) { 73 | type = DataType::Friendster; 74 | } 75 | } 76 | 77 | int read_int() { 78 | char ch = getchar(); 79 | while((ch < '0' || ch > '9') && ch !='-') ch = getchar(); 80 | int tag = 1; 81 | if(ch == '-') tag = -1, ch = getchar(); 82 | int x = 0; 83 | while( ch >= '0' && ch <= '9') x = x* 10 + ch -'0', ch = getchar(); 84 | return x * tag; 85 | } 86 | 87 | unsigned int read_unsigned_int() { 88 | char ch = getchar(); 89 | while((ch < '0' || ch > '9') ) ch = getchar(); 90 | unsigned int x = 0; 91 | while( ch >= '0' && ch <= '9') x = x* 10 + ch -'0', ch = getchar(); 92 | return x; 93 | } 94 | 95 | void long_add(long long &low, long long &high, int num) { 96 | if( low + num < 0) { 97 | low = 0; 98 | ++high; 99 | } 100 | else { 101 | low += num; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/disjoint_set_union.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/disjoint_set_union.h" 2 | 3 | DisjointSetUnion::DisjointSetUnion(int n) { 4 | size = n; 5 | set_size = n; 6 | father = new int[n]; 7 | } 8 | 9 | DisjointSetUnion::~DisjointSetUnion() { 10 | if( size > 0) { 11 | delete[] father; 12 | } 13 | } 14 | 15 | void DisjointSetUnion::init() { 16 | for(int i = 0; i < size; ++i) 17 | father[i] = i; 18 | set_size = size; 19 | } 20 | 21 | void DisjointSetUnion::merge(int id1, int id2) { 22 | int fa1 = get_father(id1); 23 | int fa2 = get_father(id2); 24 | if(fa1 != fa2) { 25 | --set_size; 26 | father[fa1] = fa2; 27 | } 28 | } 29 | 30 | int DisjointSetUnion::get_father(int a) { 31 | if( father[a] == a) return a; 32 | else return father[a] = get_father(father[a]); 33 | } 34 | -------------------------------------------------------------------------------- /src/fsm_test.cpp: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | int main(int argc,char *argv[]) { 18 | LabeledGraph *g; 19 | DataLoader D; 20 | 21 | // assert(argc == 4); 22 | // const std::string type = argv[1]; 23 | const std::string path = argv[1]; 24 | const int max_edge = atoi(argv[2]); 25 | const int min_support = atoi(argv[3]); 26 | 27 | DataType my_type; 28 | 29 | GetDataType(my_type, "Patents"); 30 | 31 | if(my_type == DataType::Invalid) { 32 | printf("Dataset not found!\n"); 33 | return 0; 34 | } 35 | 36 | g = new LabeledGraph(); 37 | assert(D.load_labeled_data(g,my_type,path.c_str())==true); 38 | 39 | printf("thread num: %d\n", omp_get_max_threads()); 40 | 41 | double total_time = 0; int times = 1; 42 | for(int i = 0; i < times; i++){ 43 | double this_time = 0.0; 44 | g->fsm(max_edge, min_support, &this_time); 45 | total_time += this_time; 46 | } 47 | total_time /= times; 48 | printf("Counting time cost: %.6lf s\n", total_time); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/fsm_vertex_test.cpp: -------------------------------------------------------------------------------- 1 | #undef NDEBUG 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | #include 16 | 17 | int main(int argc,char *argv[]) { 18 | LabeledGraph *g; 19 | DataLoader D; 20 | 21 | // assert(argc == 4); 22 | // const std::string type = argv[1]; 23 | const std::string path = argv[1]; 24 | const int max_edge = atoi(argv[2]); 25 | const int min_support = atoi(argv[3]); 26 | 27 | DataType my_type; 28 | 29 | GetDataType(my_type, "Patents"); 30 | 31 | if(my_type == DataType::Invalid) { 32 | printf("Dataset not found!\n"); 33 | return 0; 34 | } 35 | 36 | g = new LabeledGraph(); 37 | assert(D.load_labeled_data(g,my_type,path.c_str())==true); 38 | 39 | printf("thread num: %d\n", omp_get_max_threads()); 40 | 41 | double total_time = 0; int times = 1; 42 | for(int i = 0; i < times; i++){ 43 | double this_time = 0.0; 44 | g->fsm_vertex(max_edge, min_support, &this_time); 45 | total_time += this_time; 46 | } 47 | total_time /= times; 48 | printf("Counting time cost: %.6lf s\n", total_time); 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /src/in_exclusion_performance_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, Pattern &pattern) { 14 | int thread_num = 24; 15 | double t1,t2,t3,t4; 16 | 17 | bool is_pattern_valid; 18 | int performance_modeling_type; 19 | bool use_in_exclusion_optimize; 20 | 21 | performance_modeling_type = 1; 22 | use_in_exclusion_optimize = true; 23 | Schedule schedule_our(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 24 | assert(is_pattern_valid==true); 25 | 26 | performance_modeling_type = 2; 27 | use_in_exclusion_optimize = false; 28 | Schedule schedule_gz(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 29 | assert(is_pattern_valid==true); 30 | 31 | std::vector< std::pair > gz_pairs; 32 | schedule_gz.GraphZero_aggressive_optimize(gz_pairs); 33 | schedule_gz.add_restrict(gz_pairs); 34 | 35 | std::vector< std::vector< std::pair > >restricts; 36 | schedule_our.restricts_generate(schedule_our.get_adj_mat_ptr(), restricts); 37 | 38 | std::vector< std::pair > our_pairs; 39 | schedule_our.restrict_selection(g->v_cnt, g->e_cnt, restricts, our_pairs); 40 | schedule_our.add_restrict(our_pairs); 41 | 42 | for(int i = 0; i < 3; ++i) { 43 | t1 = get_wall_time(); 44 | long long ans_our = g->pattern_matching(schedule_our, thread_num); 45 | t2 = get_wall_time(); 46 | 47 | printf("our ans: %lld time: %.6lf\n", ans_our, t2 - t1); 48 | if(i == 2) { 49 | schedule_our.print_schedule(); 50 | for(int i = 0; i < our_pairs.size(); ++i) 51 | printf("(%d,%d)",our_pairs[i].first, our_pairs[i].second); 52 | puts(""); 53 | } 54 | fflush(stdout); 55 | } 56 | 57 | for(int i = 0; i < 3; ++i) { 58 | t3 = get_wall_time(); 59 | long long ans_gz = g->pattern_matching(schedule_gz, thread_num); 60 | t4 = get_wall_time(); 61 | 62 | printf("GZ ans: %lld time: %.6lf\n", ans_gz, t4 - t3); 63 | if(i == 2) { 64 | schedule_gz.print_schedule(); 65 | for(int i = 0; i < gz_pairs.size(); ++i) 66 | printf("(%d,%d)",gz_pairs[i].first, gz_pairs[i].second); 67 | puts(""); 68 | fflush(stdout); 69 | } 70 | } 71 | } 72 | 73 | int main(int argc,char *argv[]) { 74 | Graph *g; 75 | DataLoader D; 76 | 77 | std::string type = "Patents"; 78 | std::string path = "/home/zms/patents_input"; 79 | DataType my_type; 80 | if(type == "Patents") my_type = DataType::Patents; 81 | else { 82 | printf("invalid DataType!\n"); 83 | } 84 | 85 | assert(D.load_data(g,my_type,path.c_str())==true); 86 | 87 | printf("Load data success!\n"); 88 | fflush(stdout); 89 | Pattern pattern(6); 90 | pattern.add_edge(0, 1); 91 | pattern.add_edge(0, 2); 92 | pattern.add_edge(0, 3); 93 | pattern.add_edge(1, 2); 94 | pattern.add_edge(1, 3); 95 | pattern.add_edge(2, 4); 96 | pattern.add_edge(2, 5); 97 | pattern.add_edge(3, 4); 98 | pattern.add_edge(3, 5); 99 | test_pattern(g, pattern); 100 | /* 101 | test_pattern(g, PatternType::Rectangle); 102 | test_pattern(g, PatternType::QG3); 103 | test_pattern(g, PatternType::Pentagon); 104 | test_pattern(g, PatternType::House); 105 | test_pattern(g, PatternType::Hourglass); 106 | test_pattern(g, PatternType::Cycle_6_Tri); 107 | test_pattern(g, PatternType::Clique_7_Minus); 108 | */ 109 | /* 110 | for(int size = 3; size < 7; ++size) { 111 | MotifGenerator mg(size); 112 | std::vector patterns = mg.generate(); 113 | for(Pattern& p : patterns) { 114 | test_pattern(g, p); 115 | } 116 | } 117 | */ 118 | delete g; 119 | } 120 | -------------------------------------------------------------------------------- /src/motif_counting_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | #include "omp.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | int main(int argc,char *argv[]) { 15 | Graph *g; 16 | DataLoader D; 17 | 18 | if(argc != 3) { 19 | printf("usage: %s graph_file pattern_size\n", argv[0]); 20 | return 0; 21 | } 22 | 23 | bool ok = D.fast_load(g, argv[1]); 24 | if(!ok) { printf("Load data failed\n"); return 0; } 25 | 26 | printf("Load data success!\n"); 27 | fflush(stdout); 28 | int size = atoi(argv[2]); 29 | 30 | printf("thread num: %d\n", omp_get_max_threads()); 31 | 32 | if(size == 3) 33 | g->motif_counting_3(); 34 | else 35 | g->motif_counting(size); 36 | delete g; 37 | return 0; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/motif_generator.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/motif_generator.h" 2 | #include 3 | #include 4 | 5 | void MotifGenerator::generate_all_pattern(std::vector& vec, std::set edge_set, Pattern& p, int depth, int i, int j) 6 | { 7 | if (i == size - 1) 8 | { 9 | // its isomorphism graph has not been generated and it's connected 10 | if (s.count(edge_set) == 0 && p.check_connected()) 11 | { 12 | vec.push_back(p); 13 | p.count_all_isomorphism(s); 14 | } 15 | return; 16 | } 17 | //use edge(i,j) 18 | edge_set.insert(i * size + j); 19 | p.add_edge(i, j); 20 | if (j == size - 1) 21 | generate_all_pattern(vec, edge_set, p, depth + 1, i + 1, i + 2); 22 | else 23 | generate_all_pattern(vec, edge_set, p, depth + 1, i, j + 1); 24 | p.del_edge(i, j); 25 | edge_set.erase(i * size + j); 26 | //not use edge(i,j) 27 | if (j == size - 1) 28 | generate_all_pattern(vec, edge_set, p, depth + 1, i + 1, i + 2); 29 | else 30 | generate_all_pattern(vec, edge_set, p, depth + 1, i, j + 1); 31 | } 32 | 33 | std::vector MotifGenerator::generate() 34 | { 35 | s.clear(); 36 | std::set edge_set; 37 | edge_set.clear(); 38 | 39 | std::vector vec; 40 | vec.clear(); 41 | Pattern p(size); 42 | generate_all_pattern(vec, edge_set, p, 0, 0, 1); 43 | return vec; 44 | } -------------------------------------------------------------------------------- /src/pm_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | double test_pattern(Graph* g, Pattern &pattern) { 15 | 16 | bool is_pattern_valid; 17 | int performance_modeling_type; 18 | bool use_in_exclusion_optimize; 19 | 20 | performance_modeling_type = 1; 21 | use_in_exclusion_optimize = true; 22 | Schedule_IEP schedule_our(pattern, is_pattern_valid, performance_modeling_type, 1, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 23 | assert(is_pattern_valid==true); 24 | 25 | double t1,t2; 26 | double total_time = 0; 27 | 28 | printf("thread count: %d\n", omp_get_max_threads()); 29 | 30 | 31 | int times = 1; 32 | for(int i = 0; i < times; ++i) { 33 | t1 = get_wall_time(); 34 | long long ans_our = g->pattern_matching(schedule_our); 35 | t2 = get_wall_time(); 36 | 37 | printf("Ans: %lld time: %.6lf\n", ans_our, t2 - t1); 38 | total_time += (t2 - t1); 39 | if(i == times - 1) { 40 | schedule_our.print_schedule(); 41 | } 42 | fflush(stdout); 43 | } 44 | total_time /= 1; 45 | printf("Counting time cost: %.6lf s\n",total_time); 46 | return total_time; 47 | } 48 | 49 | int main(int argc,char *argv[]) { 50 | Graph *g; 51 | DataLoader D; 52 | 53 | if(argc != 4) { 54 | printf("usage: %s graph_file pattern_size pattern_adj_string\n", argv[0]); 55 | return 0; 56 | } 57 | 58 | bool ok = D.fast_load(g, argv[1]); 59 | // bool ok = D.load_data(g, DataType::Patents, argv[1], false); 60 | if(!ok) { printf("Load data failed\n"); return 0; } 61 | 62 | printf("Load data success!\n"); 63 | fflush(stdout); 64 | int pattern_size = atoi(argv[2]); 65 | const char* pattern_str= argv[3]; 66 | 67 | Pattern p(pattern_size, pattern_str); 68 | 69 | test_pattern(g, p); 70 | delete g; 71 | return 0; 72 | } -------------------------------------------------------------------------------- /src/prefix.cpp: -------------------------------------------------------------------------------- 1 | #include "../include/prefix.h" 2 | #include 3 | 4 | Prefix::Prefix() 5 | { 6 | data = nullptr; 7 | has_child = false; 8 | only_need_size = false; 9 | } 10 | 11 | Prefix::~Prefix() 12 | { 13 | if (data != nullptr) 14 | delete[] data; 15 | } 16 | 17 | void Prefix::init(int input_size, const int* input_data) 18 | { 19 | size = input_size; 20 | data = new int[input_size]; 21 | memcpy(data, input_data, size * sizeof(int)); 22 | } 23 | 24 | bool Prefix::operator==(const Prefix& pre) const 25 | { 26 | if (size != pre.get_size()) 27 | return false; 28 | for (int i = 0; i < size; ++i) 29 | if (data[i] != pre.get_data(i)) 30 | return false; 31 | return true; 32 | } 33 | 34 | bool Prefix::operator!=(const Prefix& pre) const 35 | { 36 | if (size != pre.get_size()) 37 | return true; 38 | for (int i = 0; i < size; ++i) 39 | if (data[i] != pre.get_data(i)) 40 | return true; 41 | return false; 42 | } 43 | 44 | bool Prefix::equal(int input_size, const int* input_data) const 45 | { 46 | if (size != input_size) 47 | return false; 48 | for (int i = 0; i < size; ++i) 49 | if (data[i] != input_data[i]) 50 | return false; 51 | return true; 52 | } 53 | -------------------------------------------------------------------------------- /src/restricts_printer.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main(int argc,char *argv[]) { 14 | 15 | int size = atoi(argv[1]); 16 | char* adj_mat = argv[2]; 17 | 18 | Pattern pattern(size, adj_mat); 19 | bool is_valid; 20 | Schedule schedule(pattern, is_valid, 0, 0, 0, 0, 0, 0); 21 | std::vector< std::vector< std::pair > > restricts; 22 | schedule.restricts_generate(schedule.get_adj_mat_ptr(), restricts); 23 | schedule.print_schedule(); 24 | for(auto &restrict : restricts) { 25 | for(auto &p : restrict) 26 | printf("(%d,%d)",p.first,p.second); 27 | puts(""); 28 | } 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /src/run_brute_force_tc.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc,char *argv[]) 13 | { 14 | if (argc != 3) 15 | { 16 | printf("Please give a name of dataset, like Patents, and a thread number."); 17 | return -1; 18 | } 19 | Graph *g; 20 | DataLoader D; 21 | 22 | std::string type = std::string(argv[1]); 23 | std::string path; 24 | DataType my_type; 25 | if (type == "Patents") 26 | { 27 | path = "/home/zms/patents_input"; 28 | my_type = DataType::Patents; 29 | } 30 | else if (type == "Orkut") 31 | { 32 | path = "/home/zms/orkut_input"; 33 | my_type = DataType::Orkut; 34 | } 35 | else { 36 | printf("Invalid dataset!\n"); 37 | return -1; 38 | } 39 | 40 | if (D.load_data(g,my_type,path.c_str()) != true) 41 | { 42 | printf("Load error."); 43 | return -1; 44 | } 45 | 46 | int thread_num = atoi(argv[2]); 47 | double t1 = get_wall_time(); 48 | g->triangle_counting_mt(thread_num); 49 | double t2 = get_wall_time(); 50 | printf("brute force %d thread TC with root symmetry time: %.6lf\n", thread_num, t2 - t1); 51 | } -------------------------------------------------------------------------------- /src/run_general_tc.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | int main(int argc,char *argv[]) 13 | { 14 | if (argc != 3) 15 | { 16 | printf("Please give a name of dataset, like Patents, and a thread number."); 17 | return -1; 18 | } 19 | Graph *g; 20 | DataLoader D; 21 | 22 | std::string type = std::string(argv[1]); 23 | std::string path; 24 | DataType my_type; 25 | if (type == "Patents") 26 | { 27 | path = "/home/zms/patents_input"; 28 | my_type = DataType::Patents; 29 | } 30 | else if (type == "Orkut") 31 | { 32 | path = "/home/zms/orkut_input"; 33 | my_type = DataType::Orkut; 34 | } 35 | else { 36 | printf("Invalid dataset!\n"); 37 | return -1; 38 | } 39 | 40 | if (D.load_data(g,my_type,path.c_str()) != true) 41 | { 42 | printf("Load error."); 43 | return -1; 44 | } 45 | 46 | Pattern tc_pattern(3); 47 | tc_pattern.add_edge(0, 1); 48 | tc_pattern.add_edge(0, 2); 49 | tc_pattern.add_edge(1, 2); 50 | bool is_pattern_valid; 51 | Schedule tc_schedule(tc_pattern, is_pattern_valid, 0, g->v_cnt, g->e_cnt); 52 | 53 | int thread_num = atoi(argv[2]); 54 | double t1 = get_wall_time(); 55 | g->pattern_matching(tc_schedule, thread_num, true); 56 | double t2 = get_wall_time(); 57 | printf("brute force %d thread TC with root symmetry time: %.6lf\n", thread_num, t2 - t1); 58 | } 59 | -------------------------------------------------------------------------------- /src/schedule_printer.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int main(int argc,char *argv[]) { 14 | 15 | Pattern pattern(PatternType::House); 16 | printf("5 "); 17 | const int* adj_mat = pattern.get_adj_mat_ptr(); 18 | for(int i = 0; i < 5; ++i) 19 | for(int j = 0; j< 5; ++j) 20 | printf("%d", adj_mat[INDEX(i,j,5)]); 21 | puts(""); 22 | Pattern p(PatternType::Cycle_6_Tri); 23 | printf("6 "); 24 | const int* adj_mat2 = p.get_adj_mat_ptr(); 25 | for(int i = 0; i < 6; ++i) 26 | for(int j = 0; j< 6; ++j) 27 | printf("%d", adj_mat2[INDEX(i,j,6)]); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | enable_testing() 2 | 3 | set(GTEST_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/modules/googletest/googletest/include") 4 | set(GTEST_LIB gtest_main gtest) 5 | include_directories(${GTEST_INCLUDE_DIR}) 6 | 7 | include(GoogleTest) 8 | MESSAGE("GTEST FOUND") 9 | 10 | ADD_EXECUTABLE(pattern_matching_test pattern_matching_test.cpp) 11 | TARGET_LINK_LIBRARIES(pattern_matching_test 12 | ${GTEST_LIB} 13 | graph_mining 14 | pthread 15 | gomp) 16 | gtest_discover_tests(pattern_matching_test) 17 | 18 | ADD_EXECUTABLE(gpu_sample_test gpu_sample_test.cu) 19 | SET_PROPERTY(TARGET gpu_sample_test PROPERTY CUDA_SEPARABLE_COMPILATION ON) 20 | TARGET_LINK_LIBRARIES(gpu_sample_test 21 | ${GTEST_LIB} 22 | graph_mining 23 | pthread 24 | gomp) 25 | 26 | gtest_discover_tests(gpu_sample_test) 27 | 28 | 29 | ADD_EXECUTABLE(gpu_pattern_matching_test gpu_pattern_matching_test.cu) 30 | SET_PROPERTY(TARGET gpu_pattern_matching_test PROPERTY CUDA_SEPARABLE_COMPILATION ON) 31 | TARGET_LINK_LIBRARIES(gpu_pattern_matching_test 32 | ${GTEST_LIB} 33 | graph_mining 34 | pthread 35 | gomp) 36 | 37 | gtest_discover_tests(gpu_pattern_matching_test) 38 | 39 | # ADD_EXECUTABLE(performance_modeling_test performance_modeling_test.cpp) 40 | # TARGET_LINK_LIBRARIES(performance_modeling_test 41 | # ${GTEST_LIB} 42 | # graph_mining 43 | # pthread 44 | # gomp) 45 | # gtest_discover_tests(performance_modeling_test) 46 | 47 | # ADD_EXECUTABLE(restricts_generation_test restricts_generation_test.cpp) 48 | # TARGET_LINK_LIBRARIES(restricts_generation_test 49 | # ${GTEST_LIB} 50 | # graph_mining 51 | # pthread 52 | # gomp) 53 | # gtest_discover_tests(restricts_generation_test) 54 | 55 | # ADD_EXECUTABLE(schedule_compare_test schedule_compare_test.cpp) 56 | # TARGET_LINK_LIBRARIES(schedule_compare_test 57 | # ${GTEST_LIB} 58 | # graph_mining 59 | # pthread 60 | # gomp) 61 | # gtest_discover_tests(schedule_compare_test) 62 | 63 | # ADD_EXECUTABLE(restricts_compare_test restricts_compare_test.cpp) 64 | # TARGET_LINK_LIBRARIES(restricts_compare_test 65 | # ${GTEST_LIB} 66 | # graph_mining 67 | # pthread 68 | # gomp) 69 | # gtest_discover_tests(restricts_compare_test) 70 | 71 | # ADD_EXECUTABLE(performance_compare_test performance_compare_test.cpp) 72 | # TARGET_LINK_LIBRARIES(performance_compare_test 73 | # ${GTEST_LIB} 74 | # graph_mining 75 | # pthread 76 | # gomp) 77 | # gtest_discover_tests(performance_compare_test) 78 | 79 | -------------------------------------------------------------------------------- /test/gpu_pattern_matching_test.cu: -------------------------------------------------------------------------------- 1 | #include "../gpu/src/gpu_pattern_matching.cuh" 2 | #include "../include/common.h" 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include <../include/dataloader.h> 6 | #include <../include/graph.h> 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | TEST(gpu_pattern_matching_test, gpu_pattern_matching_test_patents) { 14 | Graph *g; 15 | DataLoader D; 16 | bool ok = D.fast_load(g, "/home/cqq/data/patents.g"); 17 | ASSERT_EQ(ok, true); 18 | 19 | int size[] = {5, 6, 6, 6, 7, 7}; 20 | 21 | const char *pattern[50] = {"0111010011100011100001100", 22 | "011011101110110101011000110000101000", 23 | "011111101000110111101010101101101010", 24 | "011110101101110000110000100001010010", 25 | "0111111101111111011101110100111100011100001100000", 26 | "0111111101111111011001110100111100011000001100000"}; 27 | 28 | long long ans[] = {7375094981, 19186236035, 9600941704, 86946614984, 138737462736, 37814965911}; 29 | 30 | for (int i = 0; i < 6; i++) { 31 | Pattern p(size[i], pattern[i]); 32 | bool is_pattern_valid = false; 33 | Schedule_IEP schedule_iep(p, is_pattern_valid, 1, 1, true, g->v_cnt, g->e_cnt, g->tri_cnt); 34 | ASSERT_EQ(is_pattern_valid, true); 35 | 36 | PatternMatchingDeviceContext *context; 37 | gpuErrchk(cudaMallocManaged((void **)&context, sizeof(PatternMatchingDeviceContext))); 38 | context->init(g, schedule_iep); 39 | 40 | uint32_t buffer_size = VertexSet::max_intersection_size; 41 | int max_active_blocks_per_sm; 42 | cudaOccupancyMaxActiveBlocksPerMultiprocessor(&max_active_blocks_per_sm, gpu_pattern_matching, THREADS_PER_BLOCK, context->block_shmem_size); 43 | printf("Max number of active warps per SM: %d\n", max_active_blocks_per_sm * WARPS_PER_BLOCK); 44 | 45 | unsigned long long sum = 0; 46 | 47 | gpu_pattern_matching<<block_shmem_size>>>(g->e_cnt, buffer_size, context); 48 | 49 | gpuErrchk(cudaPeekAtLastError()); 50 | gpuErrchk(cudaDeviceSynchronize()); 51 | gpuErrchk(cudaMemcpy(&sum, context->dev_sum, sizeof(sum), cudaMemcpyDeviceToHost)); 52 | 53 | sum /= schedule_iep.get_in_exclusion_optimize_redundancy(); 54 | 55 | printf("count %llu\n", sum); 56 | ASSERT_EQ(sum, ans[i]); 57 | 58 | context->destroy(); 59 | gpuErrchk(cudaFree(context)); 60 | } 61 | } -------------------------------------------------------------------------------- /test/gpu_sample_test.cu: -------------------------------------------------------------------------------- 1 | #include 2 | #include <../include/graph.h> 3 | #include <../include/dataloader.h> 4 | #include "../include/pattern.h" 5 | #include "../include/schedule.h" 6 | #include "../include/common.h" 7 | #include "../gpu/gpu_test.cuh" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | TEST(gpu_sample_test,gpu_sample_none_test){ 14 | int n = 100000; 15 | int *a = new int[n]; 16 | int *b = new int[n]; 17 | for(int i = 0; i < n; i++) { 18 | a[i] = rand() % (0x3f3f3f3f); 19 | b[i] = rand() % (0x3f3f3f3f); 20 | } 21 | test(n, a, b); 22 | for(int i = 0; i < n; i++){ 23 | ASSERT_EQ(a[i], b[i]); 24 | } 25 | } -------------------------------------------------------------------------------- /test/gtest_main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[]) { 5 | int result = 0; 6 | 7 | ::testing::InitGoogleTest(&argc, argv); 8 | //MPI_Init(&argc, &argv); 9 | result = RUN_ALL_TESTS(); 10 | //MPI_Finalize(); 11 | 12 | return result; 13 | } 14 | -------------------------------------------------------------------------------- /test/pattern_matching_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include <../include/graph.h> 3 | #include <../include/dataloader.h> 4 | #include "../include/pattern.h" 5 | #include "../include/schedule.h" 6 | #include "../include/common.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | TEST(pattern_matching_test, pattern_matching_patents_Cycle6Tri) { 13 | Graph *g; 14 | DataLoader D; 15 | 16 | std::string type = "Patents"; 17 | std::string path = "/home/cqq/data/patents_input"; 18 | DataType my_type; 19 | if(type == "Patents") my_type = DataType::Patents; 20 | else { 21 | printf("invalid DataType!\n"); 22 | } 23 | 24 | ASSERT_EQ(D.load_data(g,my_type,path.c_str()), true); 25 | 26 | printf("Load data success!\n"); 27 | fflush(stdout); 28 | 29 | Pattern pattern(PatternType::Cycle_6_Tri); 30 | 31 | bool is_pattern_valid = false; 32 | int performance_modeling_type = 0; 33 | bool use_in_exclusion_optimize = false; 34 | Schedule_IEP schedule(pattern, is_pattern_valid, performance_modeling_type, 0, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 35 | ASSERT_EQ(is_pattern_valid, true); 36 | 37 | std::vector< std::pair > pairs; 38 | schedule.aggressive_optimize(pairs); 39 | schedule.add_restrict(pairs); 40 | 41 | printf("aggressive optimize success!\n"); 42 | fflush(stdout); 43 | 44 | int thread_num = 24; 45 | double t1,t2; 46 | long long ans; 47 | 48 | printf("pattern_matching begin\n"); 49 | fflush(stdout); 50 | 51 | t1 = get_wall_time(); 52 | ans = g->pattern_matching(schedule, thread_num); 53 | t2 = get_wall_time(); 54 | 55 | printf("ans: %lld time: %.6lf\n", ans, t2 - t1); 56 | 57 | ASSERT_EQ(ans, 19186236035LL); 58 | 59 | delete g; 60 | } 61 | -------------------------------------------------------------------------------- /test/performance_compare_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include <../include/graph.h> 3 | #include <../include/dataloader.h> 4 | #include "../include/pattern.h" 5 | #include "../include/schedule.h" 6 | #include "../include/common.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | void test_pattern(Graph* g, PatternType type) { 13 | Pattern pattern(type); 14 | int thread_num = 24; 15 | double t1,t2,t3,t4; 16 | 17 | printf("test pattern : "); 18 | PatternType_printer(type); 19 | 20 | bool is_pattern_valid; 21 | int performance_modeling_type; 22 | bool use_in_exclusion_optimize = false; 23 | 24 | performance_modeling_type = 1; 25 | Schedule schedule_our(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 26 | ASSERT_EQ(is_pattern_valid, true); 27 | 28 | performance_modeling_type = 2; 29 | Schedule schedule_gz(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 30 | ASSERT_EQ(is_pattern_valid, true); 31 | 32 | std::vector< std::pair > gz_pairs; 33 | schedule_gz.GraphZero_aggressive_optimize(gz_pairs); 34 | schedule_gz.add_restrict(gz_pairs); 35 | 36 | std::vector< std::vector< std::pair > >restricts; 37 | schedule_our.restricts_generate(schedule_our.get_adj_mat_ptr(), restricts); 38 | printf("res size = %d\n", restricts.size()); 39 | 40 | std::vector< std::pair > our_pairs; 41 | schedule_our.restrict_selection(g->v_cnt, g->e_cnt, restricts, our_pairs); 42 | schedule_our.add_restrict(our_pairs); 43 | 44 | t3 = get_wall_time(); 45 | long long ans_gz = g->pattern_matching(schedule_gz, thread_num); 46 | t4 = get_wall_time(); 47 | 48 | t1 = get_wall_time(); 49 | long long ans_our = g->pattern_matching(schedule_our, thread_num); 50 | t2 = get_wall_time(); 51 | 52 | printf("our ans: %lld time: %.6lf\n", ans_our, t2 - t1); 53 | schedule_our.print_schedule(); 54 | for(int i = 0; i < our_pairs.size(); ++i) 55 | printf("(%d,%d)",our_pairs[i].first, our_pairs[i].second); 56 | puts(""); 57 | 58 | printf("GZ ans: %lld time: %.6lf\n", ans_gz, t4 - t3); 59 | schedule_gz.print_schedule(); 60 | for(int i = 0; i < gz_pairs.size(); ++i) 61 | printf("(%d,%d)",gz_pairs[i].first, gz_pairs[i].second); 62 | puts(""); 63 | fflush(stdout); 64 | } 65 | 66 | TEST(performance_compare_test, performance_compare_patents) { 67 | Graph *g; 68 | DataLoader D; 69 | 70 | std::string type = "Patents"; 71 | std::string path = "/home/zms/patents_input"; 72 | DataType my_type; 73 | if(type == "Patents") my_type = DataType::Patents; 74 | else { 75 | printf("invalid DataType!\n"); 76 | } 77 | 78 | Pattern pattern(PatternType::House); 79 | 80 | ASSERT_EQ(D.load_data(g,my_type,path.c_str()),true); 81 | 82 | printf("Load data success!\n"); 83 | fflush(stdout); 84 | 85 | test_pattern(g, PatternType::Cycle_6_Tri); 86 | test_pattern(g, PatternType::Cycle_6_Tri); 87 | test_pattern(g, PatternType::Cycle_6_Tri); 88 | // test_pattern(g, PatternType::Rectangle); 89 | // test_pattern(g, PatternType::QG3); 90 | // test_pattern(g, PatternType::Pentagon); 91 | // test_pattern(g, PatternType::House); 92 | // test_pattern(g, PatternType::Hourglass); 93 | // test_pattern(g, PatternType::Clique_7_Minus); 94 | 95 | delete g; 96 | } 97 | -------------------------------------------------------------------------------- /test/performance_modeling_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include <../include/graph.h> 3 | #include <../include/dataloader.h> 4 | #include "../include/pattern.h" 5 | #include "../include/schedule.h" 6 | #include "../include/common.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | TEST(performance_modeling_test, performance_modeling_patents_qg3) { 13 | Graph *g; 14 | DataLoader D; 15 | 16 | std::string type = "Patents"; 17 | std::string path = "/home/zms/patents_input"; 18 | DataType my_type; 19 | if(type == "Patents") my_type = DataType::Patents; 20 | else { 21 | printf("invalid DataType!\n"); 22 | } 23 | 24 | ASSERT_EQ(D.load_data(g,my_type,path.c_str()),true); 25 | 26 | printf("Load data success!\n"); 27 | fflush(stdout); 28 | 29 | Pattern pattern(PatternType::House); 30 | 31 | bool is_pattern_valid = false; 32 | int performance_modeling_type = 1; 33 | bool use_in_exclusion_optimize = false; 34 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 35 | ASSERT_EQ(is_pattern_valid, true); 36 | 37 | printf("performance modeling adj_mat\n"); 38 | schedule.print_schedule(); 39 | 40 | 41 | std::vector< std::pair > pairs; 42 | schedule.aggressive_optimize(pairs); 43 | schedule.add_restrict(pairs); 44 | 45 | printf("aggressive optimize success!\n"); 46 | fflush(stdout); 47 | 48 | int thread_num = 24; 49 | double t1,t2; 50 | long long ans; 51 | 52 | printf("pattern_matching begin\n"); 53 | fflush(stdout); 54 | 55 | t1 = get_wall_time(); 56 | ans = g->pattern_matching(schedule, thread_num); 57 | t2 = get_wall_time(); 58 | 59 | printf("ans: %lld time: %.6lf\n", ans, t2 - t1); 60 | 61 | delete g; 62 | } 63 | -------------------------------------------------------------------------------- /test/restricts_compare_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include <../include/graph.h> 3 | #include <../include/dataloader.h> 4 | #include "../include/pattern.h" 5 | #include "../include/schedule.h" 6 | #include "../include/common.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | void test_pattern(Graph* g, PatternType type) { 13 | Pattern pattern(type); 14 | int thread_num = 24; 15 | double t1,t2,t3,t4; 16 | 17 | printf("test pattern : "); 18 | PatternType_printer(type); 19 | 20 | bool is_pattern_valid; 21 | int performance_modeling_type; 22 | bool use_in_exclusion_optimize = false; 23 | 24 | performance_modeling_type = 2; 25 | Schedule schedule_our(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 26 | ASSERT_EQ(is_pattern_valid, true); 27 | 28 | performance_modeling_type = 2; 29 | Schedule schedule_gz(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 30 | ASSERT_EQ(is_pattern_valid, true); 31 | 32 | std::vector< std::pair > gz_pairs; 33 | schedule_gz.GraphZero_aggressive_optimize(gz_pairs); 34 | schedule_gz.add_restrict(gz_pairs); 35 | 36 | std::vector< std::vector< std::pair > >restricts; 37 | schedule_our.restricts_generate(schedule_our.get_adj_mat_ptr(), restricts); 38 | printf("res size = %d\n", restricts.size()); 39 | 40 | std::vector< std::pair > our_pairs; 41 | schedule_our.restrict_selection(g->v_cnt, g->e_cnt, restricts, our_pairs); 42 | schedule_our.add_restrict(our_pairs); 43 | 44 | t3 = get_wall_time(); 45 | long long ans_gz = g->pattern_matching(schedule_gz, thread_num); 46 | t4 = get_wall_time(); 47 | 48 | t1 = get_wall_time(); 49 | long long ans_our = g->pattern_matching(schedule_our, thread_num); 50 | t2 = get_wall_time(); 51 | 52 | printf("our ans: %lld time: %.6lf\n", ans_our, t2 - t1); 53 | schedule_our.print_schedule(); 54 | for(int i = 0; i < our_pairs.size(); ++i) 55 | printf("(%d,%d)",our_pairs[i].first, our_pairs[i].second); 56 | puts(""); 57 | 58 | printf("GZ ans: %lld time: %.6lf\n", ans_gz, t4 - t3); 59 | schedule_gz.print_schedule(); 60 | for(int i = 0; i < gz_pairs.size(); ++i) 61 | printf("(%d,%d)",gz_pairs[i].first, gz_pairs[i].second); 62 | puts(""); 63 | } 64 | 65 | TEST(restricts_compare_test, restricts_compare_patents) { 66 | Graph *g; 67 | DataLoader D; 68 | 69 | std::string type = "Patents"; 70 | std::string path = "/home/zms/patents_input"; 71 | DataType my_type; 72 | if(type == "Patents") my_type = DataType::Patents; 73 | else { 74 | printf("invalid DataType!\n"); 75 | } 76 | 77 | Pattern pattern(PatternType::House); 78 | 79 | ASSERT_EQ(D.load_data(g,my_type,path.c_str()),true); 80 | 81 | printf("Load data success!\n"); 82 | fflush(stdout); 83 | 84 | // test_pattern(g, PatternType::Rectangle); 85 | // test_pattern(g, PatternType::QG3); 86 | // test_pattern(g, PatternType::Pentagon); 87 | // test_pattern(g, PatternType::House); 88 | // test_pattern(g, PatternType::Hourglass); 89 | test_pattern(g, PatternType::Cycle_6_Tri); 90 | // test_pattern(g, PatternType::Clique_7_Minus); 91 | 92 | delete g; 93 | } 94 | -------------------------------------------------------------------------------- /test/restricts_generation_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include <../include/graph.h> 3 | #include <../include/dataloader.h> 4 | #include "../include/pattern.h" 5 | #include "../include/schedule.h" 6 | #include "../include/common.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | void test_pattern(Graph *g, PatternType type) { 13 | 14 | Pattern pattern(type); 15 | 16 | printf("test pattern : "); 17 | PatternType_printer(type); 18 | 19 | bool is_pattern_valid; 20 | int performance_modeling_type = 0; 21 | bool use_in_exclusion_optimize = false; 22 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 23 | ASSERT_EQ(is_pattern_valid, true); 24 | 25 | std::vector< std::vector< std::pair > >pairs_group; 26 | schedule.aggressive_optimize_get_all_pairs(pairs_group); 27 | 28 | std::vector< std::pair > gz_pairs; 29 | schedule.GraphZero_aggressive_optimize(gz_pairs); 30 | 31 | schedule.add_restrict(gz_pairs); 32 | 33 | int thread_num = 24; 34 | double t1,t2; 35 | long long ans_gz; 36 | 37 | t1 = get_wall_time(); 38 | ans_gz = g->pattern_matching(schedule, thread_num); 39 | t2 = get_wall_time(); 40 | 41 | printf("GraphZero's ans: %lld time: %.6lf\n restricts: ", ans_gz, t2 - t1); 42 | for(int i = 0; i < gz_pairs.size(); ++i) 43 | printf("(%d,%d)",gz_pairs[i].first, gz_pairs[i].second); 44 | puts(""); 45 | fflush(stdout); 46 | 47 | for(int rank = 0; rank < pairs_group.size(); ++rank) { 48 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 49 | ASSERT_EQ(is_pattern_valid, true); 50 | 51 | schedule.add_restrict(pairs_group[rank]); 52 | 53 | int thread_num = 24; 54 | double t1,t2; 55 | long long ans; 56 | 57 | t1 = get_wall_time(); 58 | ans = g->pattern_matching(schedule, thread_num); 59 | t2 = get_wall_time(); 60 | 61 | if( ans != ans_gz) continue; 62 | printf("Ours' ans: %lld time: %.6lf\n restricts: ", ans, t2 - t1); 63 | for(int i = 0; i < pairs_group[rank].size(); ++i) 64 | printf("(%d,%d)", pairs_group[rank][i].first, pairs_group[rank][i].second); 65 | puts(""); 66 | fflush(stdout); 67 | 68 | } 69 | } 70 | 71 | TEST(restricts_generation_test, restricts_generation_pattern3x3) { 72 | Graph *g; 73 | DataLoader D; 74 | 75 | std::string type = "Patents"; 76 | std::string path = "/home/zms/patents_input"; 77 | DataType my_type; 78 | if(type == "Patents") my_type = DataType::Patents; 79 | else { 80 | printf("invalid DataType!\n"); 81 | } 82 | 83 | ASSERT_EQ(D.load_data(g,my_type,path.c_str()), true); 84 | 85 | printf("Load data success!\n"); 86 | fflush(stdout); 87 | 88 | 89 | // test_pattern(g, PatternType::Rectangle); 90 | // test_pattern(g, PatternType::Pentagon); 91 | // test_pattern(g, PatternType::House); 92 | // test_pattern(g, PatternType::Hourglass); 93 | test_pattern(g, PatternType::Cycle_6_Tri); 94 | test_pattern(g, PatternType::Clique_7_Minus); 95 | 96 | delete g; 97 | } 98 | -------------------------------------------------------------------------------- /test/schedule_compare_test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include <../include/graph.h> 3 | #include <../include/dataloader.h> 4 | #include "../include/pattern.h" 5 | #include "../include/schedule.h" 6 | #include "../include/common.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | void test_pattern(Graph* g, PatternType type) { 13 | Pattern pattern(type); 14 | 15 | printf("test pattern : "); 16 | PatternType_printer(type); 17 | 18 | bool is_pattern_valid; 19 | int performance_modeling_type; 20 | bool use_in_exclusion_optimize = false; 21 | 22 | performance_modeling_type = 1; 23 | Schedule schedule_our(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 24 | ASSERT_EQ(is_pattern_valid, true); 25 | 26 | performance_modeling_type = 2; 27 | Schedule schedule_gz(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt); 28 | ASSERT_EQ(is_pattern_valid, true); 29 | 30 | std::vector< std::pair > gz_pairs; 31 | schedule_gz.GraphZero_aggressive_optimize(gz_pairs); 32 | schedule_gz.add_restrict(gz_pairs); 33 | 34 | std::vector< std::pair > our_pairs; 35 | schedule_our.GraphZero_aggressive_optimize(our_pairs); 36 | schedule_our.add_restrict(our_pairs); 37 | 38 | int thread_num = 24; 39 | double t1,t2,t3,t4; 40 | 41 | t1 = get_wall_time(); 42 | long long ans_our = g->pattern_matching(schedule_our, thread_num); 43 | t2 = get_wall_time(); 44 | 45 | t3 = get_wall_time(); 46 | long long ans_gz = g->pattern_matching(schedule_gz, thread_num); 47 | t4 = get_wall_time(); 48 | 49 | printf("our ans: %lld time: %.6lf\n", ans_our, t2 - t1); 50 | schedule_our.print_schedule(); 51 | for(int i = 0; i < our_pairs.size(); ++i) 52 | printf("(%d,%d)",our_pairs[i].first, our_pairs[i].second); 53 | puts(""); 54 | 55 | printf("GZ ans: %lld time: %.6lf\n", ans_gz, t4 - t3); 56 | schedule_gz.print_schedule(); 57 | for(int i = 0; i < gz_pairs.size(); ++i) 58 | printf("(%d,%d)",gz_pairs[i].first, gz_pairs[i].second); 59 | puts(""); 60 | } 61 | 62 | TEST(schedule_compare_test, schedule_compare_patents) { 63 | Graph *g; 64 | DataLoader D; 65 | 66 | std::string type = "Patents"; 67 | std::string path = "/home/zms/patents_input"; 68 | DataType my_type; 69 | if(type == "Patents") my_type = DataType::Patents; 70 | else { 71 | printf("invalid DataType!\n"); 72 | } 73 | 74 | Pattern pattern(PatternType::House); 75 | 76 | ASSERT_EQ(D.load_data(g,my_type,path.c_str()),true); 77 | 78 | printf("Load data success!\n"); 79 | fflush(stdout); 80 | 81 | // test_pattern(g, PatternType::Rectangle); 82 | test_pattern(g, PatternType::QG3); 83 | /* test_pattern(g, PatternType::Pentagon); 84 | test_pattern(g, PatternType::House); 85 | test_pattern(g, PatternType::Hourglass); 86 | test_pattern(g, PatternType::Cycle_6_Tri); 87 | test_pattern(g, PatternType::Clique_7_Minus); 88 | */ 89 | delete g; 90 | } 91 | -------------------------------------------------------------------------------- /tianhe/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ADD_EXECUTABLE(baseline_test baseline_test.cpp) 2 | TARGET_LINK_LIBRARIES(baseline_test graph_mining) 3 | 4 | #ADD_EXECUTABLE(sigmod2020_test sigmod2020_test.cpp) 5 | #TARGET_LINK_LIBRARIES(sigmod2020_test graph_mining) 6 | 7 | #ADD_EXECUTABLE(triangle_test triangle_test.cpp) 8 | #TARGET_LINK_LIBRARIES(triangle_test graph_mining) 9 | 10 | #ADD_EXECUTABLE(in_exclusion_optimize_test in_exclusion_optimize_test.cpp) 11 | #TARGET_LINK_LIBRARIES(in_exclusion_optimize_test graph_mining) 12 | 13 | #ADD_EXECUTABLE(all_schedule_test all_schedule_test.cpp) 14 | #TARGET_LINK_LIBRARIES(all_schedule_test graph_mining) 15 | 16 | #ADD_EXECUTABLE(performance_test performance_test.cpp) 17 | #TARGET_LINK_LIBRARIES(performance_test graph_mining) 18 | 19 | #ADD_EXECUTABLE(schedules_test schedules_test.cpp) 20 | #TARGET_LINK_LIBRARIES(schedules_test graph_mining) 21 | 22 | #ADD_EXECUTABLE(schedules_our_generator_test schedules_our_generator_test.cpp) 23 | #TARGET_LINK_LIBRARIES(schedules_our_generator_test graph_mining) 24 | 25 | ADD_EXECUTABLE(mc_ref mc_ref.cc) 26 | TARGET_LINK_LIBRARIES(mc_ref graph_mining) 27 | -------------------------------------------------------------------------------- /tianhe/all_restricts_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, Pattern &pattern) { 14 | int thread_num = 24; 15 | long long tri_cnt = 7515023; 16 | double t1,t2; 17 | 18 | bool is_pattern_valid; 19 | int performance_modeling_type = 0; 20 | int restricts_type = 0; 21 | bool use_in_exclusion_optimize = false; 22 | 23 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, restricts_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 24 | assert(is_pattern_valid); 25 | 26 | std::vector< std::vector< std::pair > >restricts; 27 | schedule.restricts_generate(schedule.get_adj_mat_ptr(), restricts); 28 | 29 | schedule.print_schedule(); 30 | 31 | for( auto& pairs : restricts) { 32 | Schedule cur_schedule(pattern, is_pattern_valid, performance_modeling_type, restricts_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 33 | std::sort(pairs.begin(), pairs.end()); 34 | cur_schedule.add_restrict(pairs); 35 | double t1 = get_wall_time(); 36 | long long ans = g->pattern_matching(cur_schedule, thread_num); 37 | double t2 = get_wall_time(); 38 | printf("ans %lld time %.6lf\n", ans, t2 - t1); 39 | printf("%d ", pairs.size()); 40 | for(const auto& p : pairs) 41 | printf("(%d,%d)", p.first, p.second); 42 | puts(""); 43 | } 44 | { 45 | std::vector< std::pair > pairs; 46 | Schedule cur_schedule(pattern, is_pattern_valid, performance_modeling_type, restricts_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 47 | cur_schedule.GraphZero_aggressive_optimize(pairs); 48 | cur_schedule.add_restrict(pairs); 49 | double t1 = get_wall_time(); 50 | long long ans = g->pattern_matching(cur_schedule, thread_num); 51 | double t2 = get_wall_time(); 52 | printf("ans %lld time %.6lf\n", ans, t2 - t1); 53 | printf("%d ", pairs.size()); 54 | for(const auto& p : pairs) 55 | printf("(%d,%d)", p.first, p.second); 56 | puts(""); 57 | } 58 | { 59 | std::vector< std::pair > pairs; 60 | Schedule cur_schedule(pattern, is_pattern_valid, 0, 1, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 61 | double t1 = get_wall_time(); 62 | long long ans = g->pattern_matching(cur_schedule, thread_num); 63 | double t2 = get_wall_time(); 64 | printf("ans %lld time %.6lf\n", ans, t2 - t1); 65 | pairs = cur_schedule.restrict_pair; 66 | printf("%d ", pairs.size()); 67 | for(const auto& p : pairs) 68 | printf("(%d,%d)", p.first, p.second); 69 | puts(""); 70 | } 71 | } 72 | 73 | int main(int argc,char *argv[]) { 74 | Graph *g; 75 | DataLoader D; 76 | 77 | std::string type = "Patents"; 78 | std::string path = "/home/zms/patents_input"; 79 | DataType my_type; 80 | if(type == "Patents") my_type = DataType::Patents; 81 | else { 82 | printf("invalid DataType!\n"); 83 | } 84 | 85 | assert(D.load_data(g,my_type,path.c_str())==true); 86 | 87 | printf("Load data success!\n"); 88 | fflush(stdout); 89 | 90 | Pattern pattern(5); 91 | pattern.add_edge(0, 1); 92 | pattern.add_edge(0, 4); 93 | pattern.add_edge(1, 2); 94 | pattern.add_edge(1, 3); 95 | pattern.add_edge(2, 3); 96 | pattern.add_edge(2, 4); 97 | test_pattern(g, pattern); 98 | 99 | delete g; 100 | } 101 | -------------------------------------------------------------------------------- /tianhe/all_schedule_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, Pattern &pattern) { 14 | std::vector speed_up; 15 | speed_up.clear(); 16 | 17 | int thread_num = 24; 18 | double t1,t2,t3,t4; 19 | 20 | bool is_pattern_valid; 21 | int performance_modeling_type; 22 | bool use_in_exclusion_optimize; 23 | 24 | int size = pattern.get_size(); 25 | const int* adj_mat = pattern.get_adj_mat_ptr(); 26 | int rank[size]; 27 | for(int i = 0; i < size; ++i) rank[i] = i; 28 | do{ 29 | Pattern cur_pattern(size); 30 | for(int i = 0; i < size; ++i) 31 | for(int j = 0; j < i; ++j) 32 | if( adj_mat[INDEX(i,j,size)]) 33 | cur_pattern.add_edge(rank[i],rank[j]); 34 | 35 | bool valid = true; 36 | const int* cur_adj_mat = cur_pattern.get_adj_mat_ptr(); 37 | for(int i = 1; i < size; ++i) { 38 | bool have_edge = false; 39 | for(int j = 0; j < i; ++j) 40 | if(cur_adj_mat[INDEX(i,j,size)]) { 41 | have_edge = true; 42 | break; 43 | } 44 | if(!have_edge) { 45 | valid = false; 46 | break; 47 | } 48 | } 49 | if(!valid) continue; 50 | 51 | Schedule schedule_our(cur_pattern, is_pattern_valid, 0, 1, false, g->v_cnt, g->e_cnt, g->tri_cnt); 52 | 53 | if(is_pattern_valid == false) continue; 54 | 55 | Schedule schedule_gz(cur_pattern, is_pattern_valid, 0, 2, false, g->v_cnt, g->e_cnt, g->tri_cnt); 56 | 57 | const auto& our_pairs = schedule_our.restrict_pair; 58 | const auto& gz_pairs = schedule_gz.restrict_pair; 59 | 60 | bool tag = true; 61 | for(const auto& gz_p : gz_pairs) { 62 | bool flag = false; 63 | for(const auto& our_p : our_pairs) 64 | if(gz_p == our_p) { 65 | flag = true; 66 | break; 67 | } 68 | if(!flag) { 69 | tag = false; 70 | break; 71 | } 72 | } 73 | 74 | if(tag) continue; 75 | 76 | t1 = get_wall_time(); 77 | long long ans = g->pattern_matching(schedule_our, thread_num); 78 | t2 = get_wall_time(); 79 | 80 | t3 = get_wall_time(); 81 | long long ans2 = g->pattern_matching(schedule_gz, thread_num); 82 | t4 = get_wall_time(); 83 | 84 | printf("%lld,%lld,%.6lf,%.6lf\n", ans, ans2, t2 - t1, t4 - t3); 85 | schedule_our.print_schedule(); 86 | for(auto& p : our_pairs) 87 | printf("(%d,%d)", p.first, p.second); 88 | puts(""); 89 | for(auto& p : gz_pairs) 90 | printf("(%d,%d)", p.first, p.second); 91 | puts(""); 92 | 93 | fflush(stdout); 94 | 95 | speed_up.push_back((t4-t3)/(t2-t1)); 96 | 97 | } while( std::next_permutation(rank, rank + size)); 98 | 99 | double cnt = 0; 100 | double mx = -1; 101 | for(const auto& s : speed_up) { 102 | cnt += s; 103 | mx = std::max(mx, s); 104 | } 105 | printf("%u\n", speed_up.size()); 106 | if(speed_up.size() == 0) return; 107 | printf("%.6lf %.6lf\n", cnt / speed_up.size(), mx); 108 | } 109 | 110 | int main(int argc,char *argv[]) { 111 | Graph *g; 112 | DataLoader D; 113 | 114 | const std::string data_type = argv[1]; 115 | const std::string path = argv[2]; 116 | 117 | int size = atoi(argv[3]); 118 | char* adj_mat = argv[4]; 119 | 120 | DataType my_type; 121 | 122 | GetDataType(my_type, data_type); 123 | 124 | if( my_type == DataType::Invalid) { 125 | printf("Dataset not found!\n"); 126 | return 0; 127 | } 128 | 129 | assert(D.load_data(g,my_type,path.c_str())==true); 130 | 131 | printf("Load data success!\n"); 132 | fflush(stdout); 133 | 134 | Pattern p(size, adj_mat); 135 | test_pattern(g, p); 136 | 137 | delete g; 138 | } 139 | -------------------------------------------------------------------------------- /tianhe/baseline_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/labeled_graph.h> 3 | #include <../include/dataloader.h> 4 | #include "../include/pattern.h" 5 | #include "../include/schedule_IEP.h" 6 | #include "../include/common.h" 7 | #include "../include/motif_generator.h" 8 | #include "../include/vertex_set.h" 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int main(int argc,char *argv[]) { 17 | 18 | Graph *g; 19 | DataLoader D; 20 | 21 | using std::chrono::system_clock; 22 | auto t1 = system_clock::now(); 23 | 24 | bool ok; 25 | ok = D.fast_load(g, argv[1]); 26 | 27 | if (!ok) { 28 | printf("data load failure :-(\n"); 29 | return 0; 30 | } 31 | 32 | auto t2 = system_clock::now(); 33 | auto load_time = std::chrono::duration_cast(t2 - t1); 34 | printf("Load data success! time: %g seconds\n", load_time.count() / 1.0e6); 35 | fflush(stdout); 36 | 37 | // const char *pattern_str = "0111010011100011100001100"; // 5 house p1 38 | //const char *pattern_str = "011011101110110101011000110000101000"; // 6 p2 39 | // const char *pattern_str = "0111111101111111011101110100111100011100001100000"; // 7 p5 40 | // const char *pattern_str = "0111111101111111011001110100111100011000001100000"; // 7 p6 41 | 42 | int pattern_size = atoi(argv[2]); 43 | const char* pattern_str= argv[3]; 44 | 45 | Pattern p(pattern_size, pattern_str); 46 | printf("pattern = \n"); 47 | p.print(); 48 | printf("max intersection size %d\n", VertexSet::max_intersection_size); 49 | bool is_pattern_valid; 50 | bool use_in_exclusion_optimize = true; 51 | Schedule_IEP schedule_iep(p, is_pattern_valid, 1, 1, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, g->tri_cnt); 52 | Schedule_IEP schedule(p, is_pattern_valid, 1, 1, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, g->tri_cnt); // schedule is only used for getting redundancy 53 | schedule_iep.set_in_exclusion_optimize_redundancy(schedule.get_in_exclusion_optimize_redundancy()); 54 | 55 | if (!is_pattern_valid) { 56 | printf("pattern is invalid!\n"); 57 | return 0; 58 | } 59 | 60 | double count_t1 = get_wall_time(); 61 | int thread_count = 24; 62 | long long ans = g->pattern_matching(schedule_iep, thread_count); 63 | double count_t2 = get_wall_time(); 64 | printf("couting time= %.6lf s\n", count_t2 - count_t1); 65 | printf("ans=%lld\n", ans); 66 | 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /tianhe/house_twitter_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, Pattern &pattern, int performance_modeling_type, bool use_our_restricts) { 14 | int tri_cnt = 7515023; 15 | int thread_num = 24; 16 | double t1,t2; 17 | 18 | bool is_pattern_valid; 19 | bool use_in_exclusion_optimize = true; 20 | 21 | double t3 = get_wall_time(); 22 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 23 | assert(is_pattern_valid); 24 | printf("in_exclusion_optimize_num = %d\n", schedule.get_in_exclusion_optimize_num()); 25 | 26 | if(schedule.get_multiplicity() == 1) return; 27 | 28 | std::vector< std::pair > pairs; 29 | if(use_our_restricts) { 30 | std::vector< std::vector< std::pair > >restricts; 31 | schedule.restricts_generate(schedule.get_adj_mat_ptr(), restricts); 32 | 33 | schedule.restrict_selection(g->v_cnt, g->e_cnt, tri_cnt, restricts, pairs); 34 | schedule.add_restrict(pairs); 35 | } 36 | else { 37 | schedule.GraphZero_aggressive_optimize(pairs); 38 | schedule.add_restrict(pairs); 39 | } 40 | double t4 = get_wall_time(); 41 | 42 | t1 = get_wall_time(); 43 | long long ans = g->pattern_matching(schedule, thread_num); 44 | t2 = get_wall_time(); 45 | 46 | printf("ans %lld, %.6lf,%.6lf\n", ans,t4 - t3, t2 - t1); 47 | schedule.print_schedule(); 48 | printf("%d ",pairs.size()); 49 | for(auto& p : pairs) 50 | printf("(%d,%d)",p.first,p.second); 51 | puts(""); 52 | fflush(stdout); 53 | 54 | } 55 | 56 | int main(int argc,char *argv[]) { 57 | Graph *g; 58 | DataLoader D; 59 | 60 | std::string type = "Twitter"; 61 | std::string path = "/home/zms/twitter_input"; 62 | DataType my_type; 63 | if(type == "Twitter") my_type = DataType::Twitter; 64 | else { 65 | printf("invalid DataType!\n"); 66 | } 67 | 68 | assert(D.load_data(g,my_type,path.c_str())==true); 69 | 70 | printf("Load data success!\n"); 71 | fflush(stdout); 72 | 73 | Pattern pattern(PatternType::House); 74 | 75 | test_pattern(g, pattern, 0, 1); 76 | 77 | delete g; 78 | } 79 | -------------------------------------------------------------------------------- /tianhe/in_exclusion_optimize_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, const Pattern &pattern, int performance_modeling_type, int restricts_type, bool use_in_exclusion_optimize = false) { 14 | int thread_num = 24; 15 | double t1,t2; 16 | 17 | bool is_pattern_valid; 18 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, restricts_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, g->tri_cnt); 19 | assert(is_pattern_valid); 20 | 21 | t1 = get_wall_time(); 22 | long long ans = g->pattern_matching(schedule, thread_num); 23 | t2 = get_wall_time(); 24 | 25 | printf("ans %lld,%.6lf\n", ans, t2 - t1); 26 | schedule.print_schedule(); 27 | const auto& pairs = schedule.restrict_pair; 28 | printf("%d ",pairs.size()); 29 | for(auto& p : pairs) 30 | printf("(%d,%d)",p.first,p.second); 31 | puts(""); 32 | fflush(stdout); 33 | 34 | } 35 | 36 | int main(int argc,char *argv[]) { 37 | Graph *g; 38 | DataLoader D; 39 | 40 | const std::string type = argv[1]; 41 | const std::string path = argv[2]; 42 | 43 | int size = atoi(argv[3]); 44 | char* adj_mat = argv[4]; 45 | 46 | DataType my_type; 47 | 48 | GetDataType(my_type, type); 49 | 50 | if(my_type == DataType::Invalid) { 51 | printf("Dataset not found!\n"); 52 | return 0; 53 | } 54 | 55 | assert(D.load_data(g,my_type,path.c_str())==true); 56 | 57 | printf("Load data success!\n"); 58 | fflush(stdout); 59 | 60 | Pattern p(size, adj_mat); 61 | test_pattern(g, p, 1, 1, true); 62 | 63 | delete g; 64 | } 65 | -------------------------------------------------------------------------------- /tianhe/our_schedule_our_restricts_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, Pattern &pattern) { 14 | pattern.print(); 15 | int thread_num = 24; 16 | long long tri_cnt = 7515023; 17 | double t1,t2; 18 | 19 | bool is_pattern_valid; 20 | int performance_modeling_type = 3; 21 | bool use_in_exclusion_optimize = false; 22 | 23 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 24 | assert(is_pattern_valid); 25 | 26 | std::vector< std::vector< std::pair > >restricts; 27 | schedule.restricts_generate(schedule.get_adj_mat_ptr(), restricts); 28 | 29 | schedule.print_schedule(); 30 | 31 | for( auto& pairs : restricts) { 32 | Schedule cur_schedule(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 33 | cur_schedule.add_restrict(pairs); 34 | double t1 = get_wall_time(); 35 | long long ans = g->pattern_matching(cur_schedule, thread_num); 36 | double t2 = get_wall_time(); 37 | printf("ans %lld time %.6lf\n", ans, t2 - t1); 38 | printf("%d ", pairs.size()); 39 | for(const auto& p : pairs) 40 | printf("(%d,%d)", p.first, p.second); 41 | puts(""); 42 | } 43 | } 44 | 45 | int main(int argc,char *argv[]) { 46 | Graph *g; 47 | DataLoader D; 48 | 49 | std::string type = "Patents"; 50 | std::string path = "/home/zms/patents_input"; 51 | DataType my_type; 52 | if(type == "Patents") my_type = DataType::Patents; 53 | else { 54 | printf("invalid DataType!\n"); 55 | } 56 | 57 | assert(D.load_data(g,my_type,path.c_str())==true); 58 | 59 | printf("Load data success!\n"); 60 | fflush(stdout); 61 | 62 | 63 | int rank = 0; 64 | 65 | for(int size = 3; size < 7; ++size) { 66 | MotifGenerator mg(size); 67 | std::vector patterns = mg.generate(); 68 | int len = patterns.size(); 69 | int l = len / 10 * rank; 70 | int r = len / 10 * (rank + 1); 71 | if( rank == 9) r = len; 72 | for(int i = l; i < r; ++i) { 73 | Pattern& p = patterns[i]; 74 | printf("%d\n", size); 75 | fflush(stdout); 76 | test_pattern(g, p); 77 | } 78 | } 79 | 80 | delete g; 81 | } 82 | -------------------------------------------------------------------------------- /tianhe/performance_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, const Pattern &pattern, std::vector< std::pair > &our_pairs) { 14 | int thread_num = 24; 15 | double t1,t2; 16 | 17 | bool is_pattern_valid; 18 | Schedule schedule(pattern, is_pattern_valid, 0,0,0, g->v_cnt, g->e_cnt, g->tri_cnt); 19 | assert(is_pattern_valid); 20 | schedule.add_restrict(our_pairs); 21 | 22 | t1 = get_wall_time(); 23 | long long ans = g->pattern_matching(schedule, thread_num); 24 | t2 = get_wall_time(); 25 | 26 | printf("ans %lld,%.6lf\n", ans, t2 - t1); 27 | schedule.print_schedule(); 28 | const auto& pairs = schedule.restrict_pair; 29 | printf("%d ",pairs.size()); 30 | for(auto& p : pairs) 31 | printf("(%d,%d)",p.first,p.second); 32 | puts(""); 33 | fflush(stdout); 34 | 35 | } 36 | 37 | int main(int argc,char *argv[]) { 38 | Graph *g; 39 | DataLoader D; 40 | 41 | const std::string type = argv[1]; 42 | const std::string path = argv[2]; 43 | 44 | int size = atoi(argv[3]); 45 | char* adj_mat = argv[4]; 46 | 47 | int restricts_size = atoi(argv[5]); 48 | std::vector< std::pair > pairs; 49 | pairs.clear(); 50 | for(int i = 0; i < restricts_size; ++i) { 51 | int x = atoi(argv[6 + i * 2]); 52 | int y = atoi(argv[6 + i * 2 + 1]); 53 | pairs.push_back(std::make_pair(x,y)); 54 | } 55 | 56 | DataType my_type; 57 | 58 | GetDataType(my_type, type); 59 | 60 | if(my_type == DataType::Invalid) { 61 | printf("Dataset not found!\n"); 62 | return 0; 63 | } 64 | 65 | double t1 = get_wall_time(); 66 | assert(D.load_data(g,my_type,path.c_str())==true); 67 | double t2 = get_wall_time(); 68 | printf("Load time %.6lf\n", t2 - t1); 69 | 70 | printf("Load data success!\n"); 71 | fflush(stdout); 72 | 73 | Pattern p(size, adj_mat); 74 | test_pattern(g, p, pairs); 75 | 76 | delete g; 77 | } 78 | -------------------------------------------------------------------------------- /tianhe/schedule_restricts_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, const Pattern &pattern, int performance_modeling_type, int restricts_type, bool use_in_exclusion_optimize = false) { 14 | long long tri_cnt = 7515023; 15 | int thread_num = 24; 16 | double t1,t2; 17 | 18 | bool is_pattern_valid; 19 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, restricts_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 20 | assert(is_pattern_valid); 21 | 22 | if(schedule.get_multiplicity() == 1) return; 23 | 24 | t1 = get_wall_time(); 25 | long long ans = g->pattern_matching(schedule, thread_num); 26 | t2 = get_wall_time(); 27 | 28 | printf("ans %lld,%.6lf\n", ans, t2 - t1); 29 | schedule.print_schedule(); 30 | const auto& pairs = schedule.restrict_pair; 31 | printf("%d ",pairs.size()); 32 | for(auto& p : pairs) 33 | printf("(%d,%d)",p.first,p.second); 34 | puts(""); 35 | fflush(stdout); 36 | 37 | } 38 | 39 | int main(int argc,char *argv[]) { 40 | Graph *g; 41 | DataLoader D; 42 | 43 | std::string type = "Patents"; 44 | std::string path = "/home/zms/patents_input"; 45 | DataType my_type; 46 | if(type == "Patents") my_type = DataType::Patents; 47 | else { 48 | printf("invalid DataType!\n"); 49 | } 50 | 51 | assert(D.load_data(g,my_type,path.c_str())==true); 52 | 53 | printf("Load data success!\n"); 54 | fflush(stdout); 55 | 56 | Pattern p(atoi(argv[1]), argv[2]); 57 | test_pattern(g, p, 1, 1, true); 58 | test_pattern(g, p, 1, 1); 59 | test_pattern(g, p, 1, 2); 60 | test_pattern(g, p, 2, 1); 61 | test_pattern(g, p, 2, 2); 62 | 63 | /* 64 | int rank = atoi(argv[1]); 65 | 66 | for(int size = 3; size < 7; ++size) { 67 | MotifGenerator mg(size); 68 | std::vector patterns = mg.generate(); 69 | int len = patterns.size(); 70 | for(int i = rank; i < patterns.size(); i += 20) { 71 | Pattern& p = patterns[i]; 72 | test_pattern(g, p, 1, 1); 73 | test_pattern(g, p, 1, 2); 74 | test_pattern(g, p, 2, 1); 75 | test_pattern(g, p, 2, 2); 76 | } 77 | } 78 | */ 79 | /* 80 | Pattern p(6); 81 | p.add_edge(0, 1); 82 | p.add_edge(0, 2); 83 | p.add_edge(0, 3); 84 | p.add_edge(1, 4); 85 | p.add_edge(1, 5); 86 | test_pattern(g, p, 1, 1); 87 | test_pattern(g, p, 1, 2); 88 | test_pattern(g, p, 2, 1); 89 | test_pattern(g, p, 2, 2); 90 | */ 91 | delete g; 92 | } 93 | -------------------------------------------------------------------------------- /tianhe/schedule_restricts_test_old.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | void test_pattern(Graph* g, Pattern &pattern, int performance_modeling_type, bool use_our_restricts) { 14 | int tri_cnt = 7515023; 15 | int thread_num = 24; 16 | double t1,t2; 17 | 18 | bool is_pattern_valid; 19 | bool use_in_exclusion_optimize = false; 20 | 21 | double t3 = get_wall_time(); 22 | Schedule schedule(pattern, is_pattern_valid, performance_modeling_type, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, tri_cnt); 23 | assert(is_pattern_valid); 24 | 25 | if(schedule.get_multiplicity() == 1) return; 26 | 27 | std::vector< std::pair > pairs; 28 | if(use_our_restricts) { 29 | std::vector< std::vector< std::pair > >restricts; 30 | schedule.restricts_generate(schedule.get_adj_mat_ptr(), restricts); 31 | 32 | schedule.restrict_selection(g->v_cnt, g->e_cnt, tri_cnt, restricts, pairs); 33 | schedule.add_restrict(pairs); 34 | } 35 | else { 36 | schedule.GraphZero_aggressive_optimize(pairs); 37 | schedule.add_restrict(pairs); 38 | } 39 | double t4 = get_wall_time(); 40 | 41 | t1 = get_wall_time(); 42 | long long ans = g->pattern_matching(schedule, thread_num); 43 | t2 = get_wall_time(); 44 | 45 | printf("ans %lld, %.6lf,%.6lf\n", ans,t4 - t3, t2 - t1); 46 | schedule.print_schedule(); 47 | printf("%d ",pairs.size()); 48 | for(auto& p : pairs) 49 | printf("(%d,%d)",p.first,p.second); 50 | puts(""); 51 | fflush(stdout); 52 | 53 | } 54 | 55 | int main(int argc,char *argv[]) { 56 | Graph *g; 57 | DataLoader D; 58 | 59 | std::string type = "Patents"; 60 | std::string path = "/home/zms/patents_input"; 61 | DataType my_type; 62 | if(type == "Patents") my_type = DataType::Patents; 63 | else { 64 | printf("invalid DataType!\n"); 65 | } 66 | 67 | assert(D.load_data(g,my_type,path.c_str())==true); 68 | 69 | printf("Load data success!\n"); 70 | fflush(stdout); 71 | 72 | 73 | int rank = 0; 74 | 75 | for(int size = 3; size < 7; ++size) { 76 | MotifGenerator mg(size); 77 | std::vector patterns = mg.generate(); 78 | int len = patterns.size(); 79 | int l = len / 10 * rank; 80 | int r = len / 10 * (rank + 1); 81 | if( rank == 9) r = len; 82 | for(int i = l; i < r; ++i) { 83 | Pattern& p = patterns[i]; 84 | printf("%d\n", size); 85 | fflush(stdout); 86 | test_pattern(g, p, 1, false); 87 | test_pattern(g, p, 1, true); 88 | test_pattern(g, p, 3, false); 89 | test_pattern(g, p, 3, true); 90 | } 91 | } 92 | 93 | delete g; 94 | } 95 | -------------------------------------------------------------------------------- /tianhe/schedules_our_generator_test.cpp: -------------------------------------------------------------------------------- 1 | // test all schedules which inner k loops are not connected with each other 2 | // and use our restricts 3 | 4 | #include <../include/graph.h> 5 | #include <../include/dataloader.h> 6 | #include "../include/pattern.h" 7 | #include "../include/schedule.h" 8 | #include "../include/common.h" 9 | #include "../include/motif_generator.h" 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | int node_cnt = 72; 17 | int my_rank; 18 | 19 | void test_pattern(Graph* g, Pattern &pattern) { 20 | int work_cnt = 0; 21 | 22 | int thread_num = 24; 23 | double t1,t2; 24 | 25 | bool is_pattern_valid; 26 | int performance_modeling_type; 27 | bool use_in_exclusion_optimize; 28 | 29 | t1 = get_wall_time(); 30 | Schedule schedule_our(pattern, is_pattern_valid, 1, 1, true, g->v_cnt, g->e_cnt, g->tri_cnt); 31 | assert(is_pattern_valid); 32 | t2 = get_wall_time(); 33 | 34 | printf("Init time : %.6lf\n", t2 - t1); 35 | 36 | int k_val = schedule_our.get_k_val(); 37 | printf("k_val : %d\n", k_val); 38 | 39 | t1 = get_wall_time(); 40 | long long ans = g->pattern_matching(schedule_our, thread_num); 41 | t2 = get_wall_time(); 42 | printf("our time : %.6lf\n", t2 - t1); 43 | 44 | int size = pattern.get_size(); 45 | const int* adj_mat = pattern.get_adj_mat_ptr(); 46 | int rank[size]; 47 | for(int i = 0; i < size; ++i) rank[i] = i; 48 | do{ 49 | Pattern cur_pattern(size); 50 | for(int i = 0; i < size; ++i) 51 | for(int j = 0; j < i; ++j) 52 | if( adj_mat[INDEX(i,j,size)]) 53 | cur_pattern.add_edge(rank[i],rank[j]); 54 | 55 | bool valid = true; 56 | const int* cur_adj_mat = cur_pattern.get_adj_mat_ptr(); 57 | for(int i = 1; i < size; ++i) { 58 | bool have_edge = false; 59 | for(int j = 0; j < i; ++j) 60 | if(cur_adj_mat[INDEX(i,j,size)]) { 61 | have_edge = true; 62 | break; 63 | } 64 | if(!have_edge) { 65 | valid = false; 66 | break; 67 | } 68 | } 69 | if(!valid) continue; 70 | 71 | int my_k = 1; 72 | for(int k = 2; k <= size; ++k) { 73 | bool flag = true; 74 | for(int i = size - k + 1; i < size; ++i) 75 | if(cur_adj_mat[INDEX(size - k,i,size)]) { 76 | flag = false; 77 | break; 78 | } 79 | if(flag == false) { 80 | my_k = k - 1; 81 | break; 82 | } 83 | } 84 | assert(my_k <= k_val); 85 | if(my_k != k_val) continue; 86 | 87 | Schedule schedule(cur_pattern, is_pattern_valid, 0, 1, false, g->v_cnt, g->e_cnt, g->tri_cnt); 88 | if(is_pattern_valid == false) continue; 89 | 90 | ++work_cnt; 91 | if( work_cnt % node_cnt != my_rank) continue; 92 | 93 | for(int i = 0; i < size; ++i,puts("")) 94 | for(int j = 0; j < size; ++j) 95 | printf("%d",cur_adj_mat[INDEX(i,j,size)]); 96 | puts(""); 97 | 98 | t1 = get_wall_time(); 99 | long long ans2 = g->pattern_matching(schedule, thread_num); 100 | t2 = get_wall_time(); 101 | 102 | if( ans2 > 0 ) { 103 | assert(ans == ans2); 104 | printf("time : %.6lf\n", t2 - t1); 105 | } 106 | else printf("timeout\n"); 107 | fflush(stdout); 108 | } while( std::next_permutation(rank, rank + size)); 109 | 110 | } 111 | 112 | int main(int argc,char *argv[]) { 113 | Graph *g; 114 | DataLoader D; 115 | 116 | const std::string data_type = argv[1]; 117 | const std::string path = argv[2]; 118 | 119 | int size = atoi(argv[3]); 120 | char* adj_mat = argv[4]; 121 | my_rank = atoi(argv[5]); 122 | 123 | DataType my_type; 124 | 125 | GetDataType(my_type, data_type); 126 | 127 | if( my_type == DataType::Invalid) { 128 | printf("Dataset not found!\n"); 129 | return 0; 130 | } 131 | 132 | assert(D.load_data(g,my_type,path.c_str())==true); 133 | 134 | printf("Load data success!\n"); 135 | fflush(stdout); 136 | 137 | Pattern p(size, adj_mat); 138 | test_pattern(g, p); 139 | 140 | delete g; 141 | } 142 | -------------------------------------------------------------------------------- /tianhe/schedules_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | int node_cnt = 72; 14 | int my_rank; 15 | 16 | void test_pattern(Graph* g, Pattern &pattern) { 17 | int work_cnt = 0; 18 | 19 | int thread_num = 24; 20 | double t3,t4; 21 | 22 | bool is_pattern_valid; 23 | int performance_modeling_type; 24 | bool use_in_exclusion_optimize; 25 | 26 | int size = pattern.get_size(); 27 | const int* adj_mat = pattern.get_adj_mat_ptr(); 28 | int rank[size]; 29 | for(int i = 0; i < size; ++i) rank[i] = i; 30 | do{ 31 | Pattern cur_pattern(size); 32 | for(int i = 0; i < size; ++i) 33 | for(int j = 0; j < i; ++j) 34 | if( adj_mat[INDEX(i,j,size)]) 35 | cur_pattern.add_edge(rank[i],rank[j]); 36 | 37 | bool valid = true; 38 | const int* cur_adj_mat = cur_pattern.get_adj_mat_ptr(); 39 | for(int i = 1; i < size; ++i) { 40 | bool have_edge = false; 41 | for(int j = 0; j < i; ++j) 42 | if(cur_adj_mat[INDEX(i,j,size)]) { 43 | have_edge = true; 44 | break; 45 | } 46 | if(!have_edge) { 47 | valid = false; 48 | break; 49 | } 50 | } 51 | if(!valid) continue; 52 | 53 | Schedule schedule_gz(cur_pattern, is_pattern_valid, 0, 2, false, g->v_cnt, g->e_cnt, g->tri_cnt); 54 | if(is_pattern_valid == false) continue; 55 | 56 | ++work_cnt; 57 | if( work_cnt % node_cnt != my_rank) continue; 58 | 59 | const auto& gz_pairs = schedule_gz.restrict_pair; 60 | 61 | t3 = get_wall_time(); 62 | long long ans2 = g->pattern_matching(schedule_gz, thread_num); 63 | t4 = get_wall_time(); 64 | int num = schedule_gz.get_in_exclusion_optimize_num_when_not_optimize(); 65 | 66 | printf("%lld,%d,%.6lf\n", ans2, num, t4 - t3); 67 | schedule_gz.print_schedule(); 68 | for(auto& p : gz_pairs) 69 | printf("(%d,%d)", p.first, p.second); 70 | puts(""); 71 | 72 | fflush(stdout); 73 | } while( std::next_permutation(rank, rank + size)); 74 | 75 | } 76 | 77 | int main(int argc,char *argv[]) { 78 | Graph *g; 79 | DataLoader D; 80 | 81 | const std::string data_type = argv[1]; 82 | const std::string path = argv[2]; 83 | 84 | int size = atoi(argv[3]); 85 | char* adj_mat = argv[4]; 86 | my_rank = atoi(argv[5]); 87 | 88 | DataType my_type; 89 | 90 | GetDataType(my_type, data_type); 91 | 92 | if( my_type == DataType::Invalid) { 93 | printf("Dataset not found!\n"); 94 | return 0; 95 | } 96 | 97 | assert(D.load_data(g,my_type,path.c_str())==true); 98 | 99 | printf("Load data success!\n"); 100 | fflush(stdout); 101 | 102 | Pattern p(size, adj_mat); 103 | test_pattern(g, p); 104 | 105 | delete g; 106 | } 107 | -------------------------------------------------------------------------------- /tianhe/sigmod2020_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | #include "../include/vertex_set.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void test_pattern(Graph* g, const Pattern &pattern, int performance_modeling_type, int restricts_type, bool use_in_exclusion_optimize = false) { 15 | printf("max intersection size %d\n", VertexSet::max_intersection_size); 16 | int thread_num = 24; 17 | double t1,t2; 18 | 19 | bool is_pattern_valid; 20 | Schedule schedule(pattern, is_pattern_valid, 1, 1, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, g->tri_cnt); 21 | assert(is_pattern_valid); 22 | 23 | t1 = get_wall_time(); 24 | long long ans = g->pattern_matching(schedule, thread_num); 25 | t2 = get_wall_time(); 26 | 27 | printf("ans %lld\n", ans); 28 | printf("time %.6lf\n", t2 - t1); 29 | // printf("intersection %lld, %lld", g->intersection_times_low, g->intersection_times_high); 30 | // printf("depth_cnt %lld %lld %lld\n", g->dep1_cnt, g->dep2_cnt, g->dep3_cnt); 31 | schedule.print_schedule(); 32 | const auto& pairs = schedule.restrict_pair; 33 | printf("%d ",pairs.size()); 34 | for(auto& p : pairs) 35 | printf("(%d,%d)",p.first,p.second); 36 | puts(""); 37 | fflush(stdout); 38 | 39 | } 40 | 41 | int main(int argc,char *argv[]) { 42 | Graph *g; 43 | DataLoader D; 44 | 45 | const std::string type = argv[1]; 46 | const std::string path = argv[2]; 47 | 48 | // int size = atoi(argv[3]); 49 | // char* adj_mat = argv[4]; 50 | 51 | // int test_type = atoi(argv[5]); 52 | 53 | DataType my_type; 54 | 55 | GetDataType(my_type, type); 56 | 57 | if(my_type == DataType::Invalid) { 58 | printf("Dataset not found!\n"); 59 | return 0; 60 | } 61 | 62 | assert(D.load_data(g,my_type,path.c_str())==true); 63 | //assert(D.load_data(g,100)==true); 64 | 65 | printf("Load data success!\n"); 66 | fflush(stdout); 67 | /* 68 | Pattern p1(PatternType::sigmod2020_guo_q1); 69 | test_pattern(g, p1, 1, 1, true); 70 | 71 | Pattern p2(PatternType::sigmod2020_guo_q2); 72 | test_pattern(g, p2, 1, 1, true); 73 | 74 | Pattern p3(PatternType::sigmod2020_guo_q3); 75 | test_pattern(g, p3, 1, 1, true); 76 | */ 77 | Pattern p4(PatternType::sigmod2020_guo_q4); 78 | test_pattern(g, p4, 1, 1, true); 79 | 80 | Pattern p5(PatternType::sigmod2020_guo_q5); 81 | test_pattern(g, p5, 1, 1, true); 82 | 83 | Pattern p6(PatternType::sigmod2020_guo_q6); 84 | test_pattern(g, p6, 1, 1, true); 85 | delete g; 86 | } 87 | -------------------------------------------------------------------------------- /tianhe/triangle_test.cpp: -------------------------------------------------------------------------------- 1 | #include <../include/graph.h> 2 | #include <../include/dataloader.h> 3 | #include "../include/pattern.h" 4 | #include "../include/schedule.h" 5 | #include "../include/common.h" 6 | #include "../include/motif_generator.h" 7 | #include "../include/vertex_set.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void test_pattern(Graph* g, const Pattern &pattern, int performance_modeling_type, int restricts_type, bool use_in_exclusion_optimize = false) { 15 | printf("max intersection size %d\n", VertexSet::max_intersection_size); 16 | int thread_num = 24; 17 | double t1,t2; 18 | 19 | bool is_pattern_valid; 20 | Schedule schedule(pattern, is_pattern_valid, 1, 1, use_in_exclusion_optimize, g->v_cnt, g->e_cnt, g->tri_cnt); 21 | assert(is_pattern_valid); 22 | 23 | t1 = get_wall_time(); 24 | long long ans = g->pattern_matching(schedule, thread_num); 25 | t2 = get_wall_time(); 26 | 27 | printf("ans %lld\n", ans); 28 | printf("time %.6lf\n", t2 - t1); 29 | // printf("intersection %lld, %lld", g->intersection_times_low, g->intersection_times_high); 30 | // printf("depth_cnt %lld %lld %lld\n", g->dep1_cnt, g->dep2_cnt, g->dep3_cnt); 31 | schedule.print_schedule(); 32 | const auto& pairs = schedule.restrict_pair; 33 | printf("%d ",pairs.size()); 34 | for(auto& p : pairs) 35 | printf("(%d,%d)",p.first,p.second); 36 | puts(""); 37 | fflush(stdout); 38 | 39 | } 40 | 41 | int main(int argc,char *argv[]) { 42 | Graph *g; 43 | DataLoader D; 44 | 45 | const std::string type = argv[1]; 46 | const std::string path = argv[2]; 47 | 48 | // int size = atoi(argv[3]); 49 | // char* adj_mat = argv[4]; 50 | 51 | // int test_type = atoi(argv[5]); 52 | 53 | DataType my_type; 54 | 55 | GetDataType(my_type, type); 56 | 57 | if(my_type == DataType::Invalid) { 58 | printf("Dataset not found!\n"); 59 | return 0; 60 | } 61 | 62 | assert(D.load_data(g,my_type,path.c_str())==true); 63 | //assert(D.load_data(g,100)==true); 64 | 65 | printf("Load data success!\n"); 66 | fflush(stdout); 67 | 68 | Pattern p(3, true); 69 | test_pattern(g, p, 1, 1, true); 70 | 71 | /* 72 | Pattern p1(PatternType::sigmod2020_guo_q1); 73 | test_pattern(g, p1, 1, 1, true); 74 | 75 | Pattern p2(PatternType::sigmod2020_guo_q2); 76 | test_pattern(g, p2, 1, 1, true); 77 | 78 | Pattern p3(PatternType::sigmod2020_guo_q3); 79 | test_pattern(g, p3, 1, 1, true); 80 | 81 | Pattern p4(PatternType::sigmod2020_guo_q4); 82 | test_pattern(g, p4, 1, 1, true); 83 | 84 | Pattern p5(PatternType::sigmod2020_guo_q5); 85 | test_pattern(g, p5, 1, 1, true); 86 | 87 | Pattern p6(PatternType::sigmod2020_guo_q6); 88 | test_pattern(g, p6, 1, 1, true); 89 | */ 90 | delete g; 91 | } 92 | --------------------------------------------------------------------------------