Skip to content

Commit acbc2f6

Browse files
authored
Merge pull request #162 from wuyazuholo/openmp
Implement parallelization for centrality and structural holes functions
2 parents b6354de + 98c843c commit acbc2f6

File tree

17 files changed

+1755
-535
lines changed

17 files changed

+1755
-535
lines changed

CMakeLists.txt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,18 @@ cmake_minimum_required(VERSION 3.23)
22

33
project(easygraph)
44

5+
option(EASYGRAPH_ENABLE_OPENMP "Enable OpenMP acceleration (auto-detect)" ON)
6+
57
option(EASYGRAPH_ENABLE_GPU "EASYGRAPH_ENABLE_GPU" OFF)
68

79
add_subdirectory(cpp_easygraph)
810

911
if (EASYGRAPH_ENABLE_GPU)
10-
1112
message("easygraph gpu module is enabled")
12-
1313
add_subdirectory(gpu_easygraph)
14-
1514
target_include_directories(cpp_easygraph
1615
PRIVATE gpu_easygraph
1716
)
18-
1917
else()
20-
2118
message("easygraph gpu module is disabled")
22-
23-
endif()
19+
endif()

cpp_easygraph/CMakeLists.txt

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ file(GLOB SOURCES
1111

1212
add_subdirectory(pybind11)
1313

14+
option(EASYGRAPH_ENABLE_OPENMP "Enable OpenMP acceleration (auto-detect)" ON)
1415
option(EASYGRAPH_ENABLE_GPU "EASYGRAPH_ENABLE_GPU" OFF)
1516

1617
if (EASYGRAPH_ENABLE_GPU)
@@ -22,7 +23,7 @@ if (EASYGRAPH_ENABLE_GPU)
2223

2324
set_property(TARGET cpp_easygraph PROPERTY CUDA_ARCHITECTURES all)
2425

25-
target_compile_definitions(cpp_easygraph
26+
target_compile_definitions(cpp_easygraph
2627
PRIVATE EASYGRAPH_ENABLE_GPU
2728
)
2829

@@ -31,14 +32,52 @@ if (EASYGRAPH_ENABLE_GPU)
3132
)
3233

3334
else()
34-
3535
pybind11_add_module(cpp_easygraph
3636
${SOURCES}
3737
)
3838

3939
endif()
4040

41-
set_target_properties(cpp_easygraph PROPERTIES
42-
LINK_SEARCH_START_STATIC ON
43-
LINK_SEARCH_END_STATIC ON
44-
)
41+
if (EASYGRAPH_ENABLE_OPENMP)
42+
if (APPLE AND CMAKE_CXX_COMPILER_ID MATCHES "Clang")
43+
find_path(EG_LIBOMP_INCLUDE_DIR
44+
NAMES omp.h
45+
PATHS
46+
/opt/homebrew/opt/libomp/include
47+
/usr/local/opt/libomp/include
48+
)
49+
50+
find_library(EG_LIBOMP_LIBRARY
51+
NAMES omp libomp
52+
PATHS
53+
/opt/homebrew/opt/libomp/lib
54+
/usr/local/opt/libomp/lib
55+
)
56+
57+
if (EG_LIBOMP_INCLUDE_DIR AND EG_LIBOMP_LIBRARY)
58+
message(STATUS "libomp found: ${EG_LIBOMP_LIBRARY}")
59+
60+
set(OpenMP_C_FLAGS "-Xpreprocessor -fopenmp" CACHE STRING "" FORCE)
61+
set(OpenMP_CXX_FLAGS "-Xpreprocessor -fopenmp" CACHE STRING "" FORCE)
62+
63+
set(OpenMP_CXX_INCLUDE_DIR "${EG_LIBOMP_INCLUDE_DIR}" CACHE PATH "" FORCE)
64+
set(OpenMP_omp_LIBRARY "${EG_LIBOMP_LIBRARY}" CACHE FILEPATH "" FORCE)
65+
else()
66+
message(STATUS
67+
"libomp not found on macOS. OpenMP will be disabled.\n"
68+
"To enable OpenMP, run: brew install libomp"
69+
)
70+
endif()
71+
endif()
72+
73+
find_package(OpenMP QUIET)
74+
endif()
75+
76+
if (OpenMP_CXX_FOUND)
77+
message(STATUS "OpenMP found, enabling parallel acceleration.")
78+
target_link_libraries(cpp_easygraph PRIVATE OpenMP::OpenMP_CXX)
79+
target_compile_definitions(cpp_easygraph PRIVATE EASYGRAPH_USE_OPENMP=1)
80+
else()
81+
message(STATUS "OpenMP not found, building in single-thread mode.")
82+
target_compile_definitions(cpp_easygraph PRIVATE EASYGRAPH_USE_OPENMP=0)
83+
endif()

cpp_easygraph/cpp_easygraph.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,20 @@ PYBIND11_MODULE(cpp_easygraph, m) {
7575
.def_property("pred", &DiGraph::get_pred,nullptr)
7676
.def("generate_linkgraph", &DiGraph_generate_linkgraph,py::arg("weight") = "weight");
7777

78+
m.def("cpp_degree_centrality", &degree_centrality, py::arg("G"));
79+
m.def("cpp_in_degree_centrality", &in_degree_centrality, py::arg("G"));
80+
m.def("cpp_out_degree_centrality", &out_degree_centrality, py::arg("G"));
7881
m.def("cpp_closeness_centrality", &closeness_centrality, py::arg("G"), py::arg("weight") = "weight", py::arg("cutoff") = py::none(), py::arg("sources") = py::none());
7982
m.def("cpp_betweenness_centrality", &betweenness_centrality, py::arg("G"), py::arg("weight") = "weight", py::arg("cutoff") = py::none(),py::arg("sources") = py::none(), py::arg("normalized") = py::bool_(true), py::arg("endpoints") = py::bool_(false));
8083
m.def("cpp_katz_centrality", &cpp_katz_centrality, py::arg("G"), py::arg("alpha") = 0.1, py::arg("beta") = 1.0, py::arg("max_iter") = 1000, py::arg("tol") = 1e-6, py::arg("normalized") = true);
84+
m.def("cpp_eigenvector_centrality", &cpp_eigenvector_centrality, py::arg("G"), py::arg("max_iter") = 100, py::arg("tol") = 1.0e-6, py::arg("nstart") = py::none(), py::arg("weight") = "weight");
8185
m.def("cpp_k_core", &core_decomposition, py::arg("G"));
8286
m.def("cpp_density", &density, py::arg("G"));
8387
m.def("cpp_constraint", &constraint, py::arg("G"), py::arg("nodes") = py::none(), py::arg("weight") = py::none(), py::arg("n_workers") = py::none());
8488
m.def("cpp_effective_size", &effective_size, py::arg("G"), py::arg("nodes") = py::none(), py::arg("weight") = py::none(), py::arg("n_workers") = py::none());
8589
m.def("cpp_efficiency", &efficiency, py::arg("G"), py::arg("nodes") = py::none(), py::arg("weight") = py::none(), py::arg("n_workers") = py::none());
8690
m.def("cpp_hierarchy", &hierarchy, py::arg("G"), py::arg("nodes") = py::none(), py::arg("weight") = py::none(), py::arg("n_workers") = py::none());
87-
m.def("cpp_pagerank", &_pagerank, py::arg("G"), py::arg("alpha") = 0.85, py::arg("max_iterator") = 500, py::arg("threshold") = 1e-6);
91+
m.def("cpp_pagerank", &_pagerank, py::arg("G"), py::arg("alpha") = 0.85, py::arg("max_iterator") = 500, py::arg("threshold") = 1e-6, py::arg("weight") = "weight");
8892
m.def("cpp_dijkstra_multisource", &_dijkstra_multisource, py::arg("G"), py::arg("sources"), py::arg("weight") = "weight", py::arg("target") = py::none());
8993
m.def("cpp_spfa", &_spfa, py::arg("G"), py::arg("source"), py::arg("weight") = "weight");
9094
m.def("cpp_clustering", &clustering, py::arg("G"), py::arg("nodes") = py::none(), py::arg("weight") = py::none());

0 commit comments

Comments
 (0)