Skip to content

Commit

Permalink
done!
Browse files Browse the repository at this point in the history
  • Loading branch information
pca006132 committed Jul 7, 2024
1 parent 4425f31 commit 5a12ffe
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 162 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ This is a modern C++ library that Github's CI verifies builds and runs on a vari

System Dependencies (note that we will automatically download the dependency if there is no such package on the system):
- [`GLM`](https://github.com/g-truc/glm/): A compact header-only vector library.
- [`Thrust`](https://github.com/NVIDIA/thrust): NVIDIA's parallel algorithms library (basically a superset of C++17 std::parallel_algorithms)
- [`tbb`](https://github.com/oneapi-src/oneTBB/): Intel's thread building blocks library. (only when `MANIFOLD_PAR=TBB` is enabled)
- [`gtest`](https://github.com/google/googletest/): Google test library (only when test is enabled, i.e. `MANIFOLD_TEST=ON`)

Expand All @@ -48,7 +47,7 @@ This library is fast with guaranteed manifold output. As such you need manifold

The most significant contribution here is a guaranteed-manifold [mesh Boolean](https://github.com/elalish/manifold/wiki/Manifold-Library#mesh-boolean) algorithm, which I believe is the first of its kind. If you know of another, please open a discussion - a mesh Boolean algorithm robust to edge cases has been an open problem for many years. Likewise, if the Boolean here ever fails you, please submit an issue! This Boolean forms the basis of a CAD kernel, as it allows simple shapes to be combined into more complex ones.

To aid in speed, this library makes extensive use of parallelization, generally through Nvidia's Thrust library. You can switch between the TBB, and serial C++ backends by setting a CMake flag. Not everything is so parallelizable, for instance a [polygon triangulation](https://github.com/elalish/manifold/wiki/Manifold-Library#polygon-triangulation) algorithm is included which is serial. Even if compiled with parallel backend, the code will still fall back to the serial version of the algorithms if the problem size is small. The WASM build is serial-only for now, but still fast.
To aid in speed, this library makes extensive use of parallelization, generally through PSTL. You can switch between the TBB, and serial C++ backends by setting a CMake flag. Not everything is so parallelizable, for instance a [polygon triangulation](https://github.com/elalish/manifold/wiki/Manifold-Library#polygon-triangulation) algorithm is included which is serial. Even if compiled with parallel backend, the code will still fall back to the serial version of the algorithms if the problem size is small. The WASM build is serial-only for now, but still fast.

> Note: OMP and CUDA backends are now removed
Expand Down Expand Up @@ -83,7 +82,6 @@ CMake flags (usage e.g. `-DMANIFOLD_DEBUG=ON`):
Offline building:
- `FETCHCONTENT_SOURCE_DIR_GLM`: path to glm source.
- `FETCHCONTENT_SOURCE_DIR_GOOGLETEST`: path to googletest source.
- `FETCHCONTENT_SOURCE_DIR_THRUST`: path to NVIDIA thrust source.

The build instructions used by our CI are in [manifold.yml](https://github.com/elalish/manifold/blob/master/.github/workflows/manifold.yml), which is a good source to check if something goes wrong and for instructions specific to other platforms, like Windows.

Expand Down
21 changes: 1 addition & 20 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 1 addition & 8 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
url = "github:google/googletest/v1.14.0";
flake = false;
};
inputs.thrust-src = {
url = "git+https://github.com/NVIDIA/thrust.git?submodules=1";
flake = false;
};
inputs.clipper2-src = {
url = "github:AngusJohnson/Clipper2";
flake = false;
};
outputs = { self, nixpkgs, flake-utils, gtest-src, thrust-src, clipper2-src }:
outputs = { self, nixpkgs, flake-utils, gtest-src, clipper2-src }:
flake-utils.lib.eachDefaultSystem
(system:
let
Expand Down Expand Up @@ -52,7 +48,6 @@
"-DMANIFOLD_PYBIND=ON"
"-DMANIFOLD_CBIND=ON"
"-DBUILD_SHARED_LIBS=ON"
"-DFETCHCONTENT_SOURCE_DIR_THRUST=${thrust-src}"
"-DMANIFOLD_PAR=${pkgs.lib.strings.toUpper parallel-backend}"
];
prePatch = ''
Expand Down Expand Up @@ -100,7 +95,6 @@
emcmake cmake -DCMAKE_BUILD_TYPE=Release \
-DFETCHCONTENT_SOURCE_DIR_GLM=${pkgs.glm.src} \
-DFETCHCONTENT_SOURCE_DIR_GOOGLETEST=${gtest-src} \
-DFETCHCONTENT_SOURCE_DIR_THRUST=${thrust-src} \
-DFETCHCONTENT_SOURCE_DIR_CLIPPER2=../clipper2 ..
'';
buildPhase = ''
Expand Down Expand Up @@ -139,7 +133,6 @@
pathspec
pkg-config
];
SKBUILD_CMAKE_DEFINE = "FETCHCONTENT_SOURCE_DIR_THRUST=${thrust-src}";
checkInputs = [
trimesh
pytest
Expand Down
25 changes: 0 additions & 25 deletions src/utilities/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,6 @@ add_library(${PROJECT_NAME} INTERFACE)
message("Parallel Backend: ${MANIFOLD_PAR}")

include(FetchContent)
FetchContent_Declare(Thrust
GIT_REPOSITORY https://github.com/NVIDIA/thrust.git
GIT_TAG 2.1.0
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
find_package(Thrust QUIET)
if(NOT Thrust_FOUND AND NOT DEFINED thrust_SOURCE_DIR)
message("thrust not found, downloading from source")
FetchContent_Populate(Thrust)
endif()

if (TRACY_ENABLE)
include(FetchContent)
FetchContent_Declare(tracy
Expand Down Expand Up @@ -62,19 +50,6 @@ target_include_directories(${PROJECT_NAME} INTERFACE
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>)
target_link_libraries(${PROJECT_NAME} INTERFACE glm::glm)

if(NOT DEFINED thrust_SOURCE_DIR)
set(thrust_SOURCE_DIR ${_THRUST_INCLUDE_DIR})
endif()

target_include_directories(${PROJECT_NAME} INTERFACE
$<BUILD_INTERFACE:${thrust_SOURCE_DIR}>
$<BUILD_INTERFACE:${thrust_SOURCE_DIR}/dependencies/libcudacxx/include>
)

target_compile_options(${PROJECT_NAME} INTERFACE
-DTHRUST_DEVICE_SYSTEM=THRUST_DEVICE_SYSTEM_${MANIFOLD_PAR}
)

if(MANIFOLD_EXCEPTIONS)
target_compile_options(${PROJECT_NAME} INTERFACE
-DMANIFOLD_EXCEPTIONS=1
Expand Down
120 changes: 14 additions & 106 deletions src/utilities/include/par.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,32 +13,12 @@
// limitations under the License.

#pragma once
#include <thrust/binary_search.h>
#include <thrust/count.h>
#include <thrust/execution_policy.h>
#include <thrust/gather.h>
#include <thrust/logical.h>
#include <thrust/remove.h>
#include <thrust/sequence.h>
#include <thrust/sort.h>
#include <thrust/system/cpp/execution_policy.h>
#include <thrust/uninitialized_copy.h>

#include <algorithm>
#include <numeric>
#if MANIFOLD_PAR == 'T'
#include <thrust/system/tbb/execution_policy.h>

#if MANIFOLD_PAR == 'T' && TBB_INTERFACE_VERSION >= 10000 && \
__has_include(<pstl/glue_execution_defs.h>)
#if MANIFOLD_PAR == 'T' && __has_include(<pstl/glue_execution_defs.h>)
#include <execution>
#endif

#define MANIFOLD_PAR_NS tbb
#else
#define MANIFOLD_PAR_NS cpp
#endif

#include "iters.h"
#include "public.h"
namespace manifold {
Expand All @@ -60,34 +40,7 @@ inline constexpr ExecutionPolicy autoPolicy(size_t size) {
return ExecutionPolicy::Par;
}

#define THRUST_DYNAMIC_BACKEND_VOID(NAME) \
template <typename... Args> \
void NAME(ExecutionPolicy policy, Args... args) { \
switch (policy) { \
case ExecutionPolicy::Par: \
thrust::NAME(thrust::MANIFOLD_PAR_NS::par, args...); \
break; \
case ExecutionPolicy::Seq: \
thrust::NAME(thrust::cpp::par, args...); \
break; \
} \
}

#define THRUST_DYNAMIC_BACKEND(NAME, RET) \
template <typename Ret = RET, typename... Args> \
Ret NAME(ExecutionPolicy policy, Args... args) { \
switch (policy) { \
case ExecutionPolicy::Par: \
return thrust::NAME(thrust::MANIFOLD_PAR_NS::par, args...); \
case ExecutionPolicy::Seq: \
break; \
} \
return thrust::NAME(thrust::cpp::par, args...); \
}

#if MANIFOLD_PAR != 'T' || \
(TBB_INTERFACE_VERSION >= 10000 && __has_include(<pstl/glue_execution_defs.h>))
#if MANIFOLD_PAR == 'T'
#if MANIFOLD_PAR == 'T' && __has_include(<pstl/glue_execution_defs.h>)
#define STL_DYNAMIC_BACKEND(NAME, RET) \
template <typename Ret = RET, typename... Args> \
Ret NAME(ExecutionPolicy policy, Args... args) { \
Expand Down Expand Up @@ -129,63 +82,6 @@ void exclusive_scan(ExecutionPolicy policy, Args... args) {
// https://github.com/llvm/llvm-project/issues/59810
std::exclusive_scan(args...);
}
template <typename DerivedPolicy, typename InputIterator1,
typename OutputIterator, typename Predicate>
OutputIterator copy_if(ExecutionPolicy policy, InputIterator1 first,
InputIterator1 last, OutputIterator result,
Predicate pred) {
#if MANIFOLD_PAR == 'T'
if (policy == ExecutionPolicy::Seq)
return std::copy_if(first, last, result, pred);
else
return std::copy_if(std::execution::par_unseq, first, last, result, pred);
#else
return std::copy_if(first, last, result, pred);
#endif
}

#else
#define STL_DYNAMIC_BACKEND(NAME, RET) THRUST_DYNAMIC_BACKEND(NAME, RET)
#define STL_DYNAMIC_BACKEND_VOID(NAME) THRUST_DYNAMIC_BACKEND_VOID(NAME)

THRUST_DYNAMIC_BACKEND_VOID(exclusive_scan)
THRUST_DYNAMIC_BACKEND(copy_if, void)
#endif

THRUST_DYNAMIC_BACKEND_VOID(gather)
THRUST_DYNAMIC_BACKEND_VOID(scatter)
THRUST_DYNAMIC_BACKEND_VOID(for_each)
THRUST_DYNAMIC_BACKEND_VOID(for_each_n)
THRUST_DYNAMIC_BACKEND_VOID(sequence)
STL_DYNAMIC_BACKEND_VOID(transform)
STL_DYNAMIC_BACKEND_VOID(uninitialized_fill)
STL_DYNAMIC_BACKEND_VOID(uninitialized_copy)
STL_DYNAMIC_BACKEND_VOID(stable_sort)
STL_DYNAMIC_BACKEND_VOID(fill)
STL_DYNAMIC_BACKEND_VOID(inclusive_scan)

// there are some issues with thrust copy
template <typename InputIterator, typename OutputIterator>
OutputIterator copy(ExecutionPolicy policy, InputIterator first,
InputIterator last, OutputIterator result) {
#if MANIFOLD_PAR == 'T' && \
(TBB_INTERFACE_VERSION >= 10000 && __has_include(<pstl/glue_execution_defs.h>))
if (policy == ExecutionPolicy::Par)
return std::copy(std::execution::par_unseq, first, last, result);
#endif
return std::copy(first, last, result);
}

template <typename InputIterator, typename OutputIterator>
OutputIterator copy_n(ExecutionPolicy policy, InputIterator first, size_t n,
OutputIterator result) {
#if MANIFOLD_PAR == 'T' && \
(TBB_INTERFACE_VERSION >= 10000 && __has_include(<pstl/glue_execution_defs.h>))
if (policy == ExecutionPolicy::Par)
return std::copy_n(std::execution::par_unseq, first, n, result);
#endif
return std::copy_n(first, n, result);
}

template <typename InputIterator1, typename InputIterator2,
typename OutputIterator>
Expand Down Expand Up @@ -227,5 +123,17 @@ STL_DYNAMIC_BACKEND(is_sorted, bool)
STL_DYNAMIC_BACKEND(reduce, void)
STL_DYNAMIC_BACKEND(count_if, int)
STL_DYNAMIC_BACKEND(remove_if, void)
STL_DYNAMIC_BACKEND(copy_if, void)

STL_DYNAMIC_BACKEND_VOID(for_each)
STL_DYNAMIC_BACKEND_VOID(for_each_n)
STL_DYNAMIC_BACKEND_VOID(transform)
STL_DYNAMIC_BACKEND_VOID(uninitialized_fill)
STL_DYNAMIC_BACKEND_VOID(uninitialized_copy)
STL_DYNAMIC_BACKEND_VOID(stable_sort)
STL_DYNAMIC_BACKEND_VOID(fill)
STL_DYNAMIC_BACKEND_VOID(inclusive_scan)
STL_DYNAMIC_BACKEND_VOID(copy)
STL_DYNAMIC_BACKEND_VOID(copy_n)

} // namespace manifold

0 comments on commit 5a12ffe

Please sign in to comment.