Skip to content

Commit af753d8

Browse files
authored
Merge pull request #36 from porumbes/dyn
Shortest edge collapse app using a preliminary cuCollections priority queue
2 parents 89011c8 + 4c49be4 commit af753d8

File tree

11 files changed

+911
-5
lines changed

11 files changed

+911
-5
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ input/*
1212
!input/sphere1.obj
1313
!input/bunnyhead.obj
1414
build/
15+
build_debug/
1516
include/rxmesh/util/git_sha1.cpp
1617
.vscode/
17-
scripts/*.log
18+
scripts/*.log

CMakeLists.txt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,22 @@ FetchContent_Declare(cereal
7979
)
8080
FetchContent_Populate(cereal)
8181

82+
# Package Management
83+
# TODO: Consider using CPM for the various libraries above
84+
include(cmake/CPM.cmake)
85+
86+
# Add cuCollection with priority queue. This should eventually come from
87+
# NVIDIA.
88+
CPMAddPackage(
89+
NAME cuco
90+
GITHUB_REPOSITORY andrewbriand/cuCollections
91+
GIT_TAG d58dd9fedde721a264c8ae960f7393a3a3b08c58
92+
OPTIONS
93+
"BUILD_TESTS OFF"
94+
"BUILD_BENCHMARKS OFF"
95+
"BUILD_EXAMPLES OFF"
96+
)
97+
8298
# Auto-detect GPU architecture
8399
include("cmake/AutoDetectCudaArch.cmake")
84100

@@ -133,7 +149,7 @@ set(cxx_flags
133149

134150
set(MSVC_XCOMPILER_FLAGS "/openmp:experimental /MP /std:c++17 /Zi")
135151
set(cuda_flags
136-
-Xcompiler=$<$<CXX_COMPILER_ID:GNU>:-Wall -fopenmp -O3 -Wno-unused-function>
152+
-Xcompiler=$<$<CXX_COMPILER_ID:GNU>:-rdynamic -Wall -fopenmp -O3 -Wno-unused-function>
137153
-Xcompiler=$<$<CXX_COMPILER_ID:MSVC>:${MSVC_XCOMPILER_FLAGS}>
138154
#Disables warning
139155
#177-D "function XXX was declared but never referenced"

apps/CMakeLists.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@ add_subdirectory(MCF)
44
add_subdirectory(Geodesic)
55
add_subdirectory(Delaunay)
66
add_subdirectory(GaussianCurvature)
7-
add_subdirectory(XPBD )
7+
add_subdirectory(XPBD)
88
#add_subdirectory(Simplification)
99
add_subdirectory(ShortestEdgeCollapse)
1010
add_subdirectory(Remesh)
11+
add_subdirectory(SECPriority)
12+
add_subdirectory(SurfaceTracking)
1113
add_subdirectory(SurfaceTracking)
1214
add_subdirectory(SCP)
1315
add_subdirectory(ARAP)
14-
add_subdirectory(Heat)
15-
16+
add_subdirectory(Heat)

apps/SECPriority/CMakeLists.txt

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
add_executable(SECPriority)
2+
3+
set(SOURCE_LIST
4+
#main.cu
5+
secp.cu
6+
secp_rxmesh.cuh
7+
secp_kernels.cuh
8+
)
9+
10+
set(COMMON_LIST
11+
../common/openmesh_trimesh.h
12+
../common/openmesh_report.h
13+
)
14+
15+
target_sources(SECPriority
16+
PRIVATE
17+
${SOURCE_LIST} ${COMMON_LIST}
18+
)
19+
20+
if (WIN32)
21+
target_compile_definitions(SECPriority
22+
PRIVATE _USE_MATH_DEFINES
23+
PRIVATE NOMINMAX
24+
PRIVATE _CRT_SECURE_NO_WARNINGS)
25+
endif()
26+
27+
set_target_properties(SECPriority PROPERTIES FOLDER "apps")
28+
29+
set_property(TARGET SECPriority PROPERTY CUDA_SEPARABLE_COMPILATION ON)
30+
31+
source_group(TREE ${CMAKE_CURRENT_LIST_DIR} PREFIX "SECPriority" FILES ${SOURCE_LIST})
32+
33+
target_link_libraries(SECPriority
34+
PRIVATE RXMesh
35+
PRIVATE gtest_main
36+
PRIVATE OpenMeshCore
37+
PRIVATE OpenMeshTools
38+
PRIVATE cuco
39+
)
40+
41+
#gtest_discover_tests( SECPriority )

apps/SECPriority/main.cu

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#include <cuco/priority_queue.cuh>
2+
#include <cuco/detail/pair.cuh>
3+
4+
#include <thrust/device_vector.h>
5+
#include <thrust/host_vector.h>
6+
7+
#include <cooperative_groups.h>
8+
#include <cuda_runtime.h>
9+
10+
#include <map>
11+
#include <vector>
12+
13+
#include <iostream>
14+
#include <random>
15+
16+
using namespace cuco;
17+
namespace cg = cooperative_groups;
18+
19+
// grab some bits from priority queue tests and benchmarks
20+
21+
// -- simulate reading the mesh, computing edge length
22+
// -- cuco:pair<float, uint32_t>
23+
//
24+
// setup pair_less template
25+
//
26+
// setup device function to pop items from queue
27+
//
28+
29+
template <typename T>
30+
struct pair_less
31+
{
32+
__host__ __device__ bool operator()(const T& a, const T& b) const
33+
{
34+
return a.first < b.first;
35+
}
36+
};
37+
38+
template <typename PairType, typename OutputIt>
39+
void generate_kv_pairs_uniform(OutputIt output_begin, OutputIt output_end)
40+
{
41+
std::random_device rd;
42+
std::mt19937 gen{rd()};
43+
44+
const auto num_keys = std::distance(output_begin, output_end);
45+
for(auto i = 0; i < num_keys; i++)
46+
{
47+
output_begin[i] = {static_cast<typename PairType::first_type>(gen()),
48+
static_cast<typename PairType::second_type>(i)};
49+
}
50+
}
51+
52+
void sp_pair()
53+
{
54+
// Setup the cuco::priority_queue
55+
const size_t insertion_size = 200;
56+
const size_t deletion_size = 100;
57+
using PairType = cuco::pair<float, uint32_t>;
58+
using Compare = pair_less<PairType>;
59+
60+
cuco::priority_queue<PairType, Compare> pq(insertion_size);
61+
62+
// Generate data for the queue
63+
std::vector<PairType> h_pairs(insertion_size);
64+
generate_kv_pairs_uniform<PairType>(h_pairs.begin(), h_pairs.end());
65+
66+
for(auto i = 0; i < h_pairs.size(); i++)
67+
{
68+
std::cout << "Priority: " << h_pairs[i].first
69+
<< "\tID: " << h_pairs[i].second << "\n";
70+
}
71+
72+
// Fill the priority queue
73+
thrust::device_vector<PairType> d_pairs(h_pairs);
74+
pq.push(d_pairs.begin(), d_pairs.end());
75+
cudaDeviceSynchronize();
76+
77+
// Pop the priority queue
78+
thrust::device_vector<PairType> d_popped(deletion_size);
79+
pq.pop(d_popped.begin(), d_popped.end());
80+
cudaDeviceSynchronize();
81+
82+
std::cout << "-----After Pop-----\n";
83+
thrust::host_vector<PairType> h_popped(d_popped);
84+
for(auto i = 0; i < h_popped.size(); i++)
85+
{
86+
std::cout << "Priority: " << h_popped[i].first
87+
<< "\tID: " << h_popped[i].second << "\n";
88+
}
89+
}
90+
91+
int main(int argc, char* argv[])
92+
{
93+
sp_pair();
94+
95+
return 0;
96+
}

apps/SECPriority/secp.cu

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
#include "gtest/gtest.h"
2+
#include "rxmesh/util/log.h"
3+
#include "rxmesh/util/macros.h"
4+
#include "rxmesh/util/util.h"
5+
6+
#include <filesystem>
7+
8+
struct arg
9+
{
10+
std::string obj_file_name = STRINGIFY(INPUT_DIR) "dragon.obj";
11+
std::string output_folder = STRINGIFY(OUTPUT_DIR);
12+
float target = 0.1;
13+
float edgefrac = 0.1;
14+
uint32_t device_id = 0;
15+
char** argv;
16+
int argc;
17+
} Arg;
18+
19+
#include "secp_rxmesh.cuh"
20+
21+
TEST(Apps, SECPriority)
22+
{
23+
using namespace rxmesh;
24+
25+
// Select device
26+
cuda_query(Arg.device_id);
27+
28+
// RXMeshDynamic rx(Arg.obj_file_name);
29+
30+
const std::string p_file = STRINGIFY(OUTPUT_DIR) +
31+
extract_file_name(Arg.obj_file_name) +
32+
"_patches";
33+
RXMeshDynamic rx(Arg.obj_file_name, p_file);
34+
if (!std::filesystem::exists(p_file)) {
35+
rx.save(p_file);
36+
}
37+
38+
ASSERT_TRUE(rx.is_edge_manifold());
39+
40+
ASSERT_TRUE(rx.is_closed());
41+
42+
uint32_t final_num_vertices = Arg.target * rx.get_num_vertices();
43+
44+
secp_rxmesh(rx, final_num_vertices, Arg.edgefrac);
45+
}
46+
47+
48+
int main(int argc, char** argv)
49+
{
50+
using namespace rxmesh;
51+
Log::init();
52+
53+
::testing::InitGoogleTest(&argc, argv);
54+
Arg.argv = argv;
55+
Arg.argc = argc;
56+
57+
58+
if (argc > 1) {
59+
if (cmd_option_exists(argv, argc + argv, "-h")) {
60+
// clang-format off
61+
RXMESH_INFO("\nUsage: SECPriority.exe < -option X>\n"
62+
" -h: Display this massage and exit\n"
63+
" -input: Input file. Input file should be under the input/ subdirectory\n"
64+
" Default is {} \n"
65+
" Hint: Only accept OBJ files\n"
66+
" -target: The fraction of output #vertices from the input\n"
67+
" -edgefrac: The fraction of edges to collapse in a round\n"
68+
" -o: JSON file output folder. Default is {} \n"
69+
" -device_id: GPU device ID. Default is {}",
70+
Arg.obj_file_name, Arg.output_folder, Arg.device_id);
71+
// clang-format on
72+
exit(EXIT_SUCCESS);
73+
}
74+
75+
if (cmd_option_exists(argv, argc + argv, "-input")) {
76+
Arg.obj_file_name =
77+
std::string(get_cmd_option(argv, argv + argc, "-input"));
78+
}
79+
if (cmd_option_exists(argv, argc + argv, "-o")) {
80+
Arg.output_folder =
81+
std::string(get_cmd_option(argv, argv + argc, "-o"));
82+
}
83+
if (cmd_option_exists(argv, argc + argv, "-device_id")) {
84+
Arg.device_id =
85+
atoi(get_cmd_option(argv, argv + argc, "-device_id"));
86+
}
87+
if (cmd_option_exists(argv, argc + argv, "-target")) {
88+
Arg.target = atof(get_cmd_option(argv, argv + argc, "-target"));
89+
}
90+
if (cmd_option_exists(argv, argc + argv, "-edgefrac")) {
91+
Arg.edgefrac = atof(get_cmd_option(argv, argv + argc, "-edgefrac"));
92+
}
93+
}
94+
95+
RXMESH_TRACE("input= {}", Arg.obj_file_name);
96+
RXMESH_TRACE("output_folder= {}", Arg.output_folder);
97+
RXMESH_TRACE("device_id= {}", Arg.device_id);
98+
RXMESH_TRACE("target= {}", Arg.target);
99+
RXMESH_TRACE("edgefrac= {}", Arg.edgefrac);
100+
101+
return RUN_ALL_TESTS();
102+
}

0 commit comments

Comments
 (0)