来自同一多面体的 Nef 多面体的多线程构造问题

Problem with multi-threaded construction of Nef Polyhedrons from a same Polyhedron

我有一个多线程程序,其中一组 3D Nef 多面体可能由同一个多面体构成,简化代码可以演示为:

#include <iostream>
#include <vector>
#include <fstream>
#include <future>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Polyhedron_3.h>
#include <CGAL/Nef_polyhedron_3.h>
#include <CGAL/boost/graph/convert_nef_polyhedron_to_polygon_mesh.h>
#include <CGAL/Polygon_mesh_processing/measure.h>
#include <CGAL/Polygon_mesh_processing/triangulate_faces.h>

typedef CGAL::Exact_predicates_exact_constructions_kernel Exact_kernel;
typedef CGAL::Polyhedron_3<Exact_kernel> Polyhedron;
typedef CGAL::Nef_polyhedron_3<Exact_kernel> Nef_polyhedron;

int main()
{
    std::ifstream ifs("mesh_a.off");
    Polyhedron poly;
    CGAL::read_off(ifs, poly);
    CGAL::Polygon_mesh_processing::triangulate_faces(poly);

    std::vector<std::future<void>> futureVec;
    for (int i = 0; i < 10; i++) {
        auto fun = [&poly]() {
            Nef_polyhedron N1(poly);
            std::cout << "test" << std::endl;
        };
        futureVec.push_back(std::async(std::launch::async, fun));
    }
    for (size_t i = 0; i < futureVec.size(); i++)
        futureVec[i].get();

    return 0;
}

mesh_a.off文件的内容是:

OFF
16 6 0
0.63 0 0
1.26 0 0
0.965876 0.294124 0
0.909198 0.245717 0
0.845645 0.206772 0
0.776783 0.178248 0
0.704306 0.160848 0
0.63 0.155 0
0.63 0 0.5
1.26 0 0.5
0.965876 0.294124 0.5
0.909198 0.245717 0.5
0.845645 0.206772 0.5
0.776783 0.178248 0.5
0.704306 0.160848 0.5
0.63 0.155 0.5
8  7 6 5 4 3 2 1 0
8  8 9 10 11 12 13 14 15
4  0 1 9 8
4  1 2 10 9
12  2 3 4 5 6 7 15 14 13 12 11 10
4  7 0 8 15

如果上面的代码运行正常,“test”这个词应该被打印 10 次。但是,每次执行的打印次数都不同,大多数时候 不打印任何东西 。 Nef Polyhedron 的构造似乎有问题导致意外线程退出,尽管没有异常抛出。如果我将打印代码行移动到 Nef Polyhedron 构造的上一行,打印行为会正常执行。

我 运行 Windows 上的程序和 IDE 是 Visual Studio 2019.

那么这段代码有什么问题呢?如何使用多线程从同一个多面体构造 Nef 多面体?

在 linux,您的程序中止

free(): corrupted unsorted chunks

CGAL::Exact_predicates_exact_constructions_kernel 目前不是线程安全的,在 2 个线程中读取相同的数字会导致损坏。有一个 PR 使它成为线程安全的:https://github.com/CGAL/cgal/pull/5402 但它还没有被合并。

如果没有这个分支,一种解决方法是使用 Simple_cartesian<mpq_class> 或类似的内核,但这比使用 Epeck 顺序构建要慢。