Multithreading CGAL 2D正则化布尔集操作库是否线程安全?
我目前正在使用标题中提到的库,请参阅 该库提供多边形和多边形集的类型,这些类型在内部表示为所谓的排列 我的问题是:这个库在多大程度上是线程安全的,也就是说,适合在其对象上进行并行计算 可以有几个级别来保证线程安全: 1) 如果我从图书馆拿了一件物品Multithreading CGAL 2D正则化布尔集操作库是否线程安全?,multithreading,concurrency,cgal,Multithreading,Concurrency,Cgal,我目前正在使用标题中提到的库,请参阅 该库提供多边形和多边形集的类型,这些类型在内部表示为所谓的排列 我的问题是:这个库在多大程度上是线程安全的,也就是说,适合在其对象上进行并行计算 可以有几个级别来保证线程安全: 1) 如果我从图书馆拿了一件物品 Polygon_set_2 S; 我也许能执行 Polygon_2 P; S.join(P); 及 在两个不同的并发执行单元/线程中并行执行,不会造成任何伤害,并获得正确的结果,就好像我按顺序完成了所有操作一样。这将是线程安全性/可能的并行性的
Polygon_set_2 S;
我也许能执行
Polygon_2 P;
S.join(P);
及
在两个不同的并发执行单元/线程中并行执行,不会造成任何伤害,并获得正确的结果,就好像我按顺序完成了所有操作一样。这将是线程安全性/可能的并行性的最高级别
2) 事实上,对我来说,一个小得多的学位就足够了。在这种情况下,S和P将是类C的成员,因此两个类实例具有不同的S和P实例。然后,我想并行计算(比如)S.join(P)
类C的实例列表,比如,通过std::async调用C的合适成员函数
为了完整起见,我在这里插入了我的项目中的一些实际代码,这使这些简洁的描述更加生动
// the following typedefs are more or less standard from the
// CGAL library examples.
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Circle_2 Circle_2;
typedef Kernel::Line_2 Line_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel> Traits_2;
typedef CGAL::General_polygon_set_2<Traits_2> Polygon_set_2;
typedef Traits_2::General_polygon_2 Polygon_2;
typedef Traits_2::General_polygon_with_holes_2 Polygon_with_holes_2;
typedef Traits_2::Curve_2 Curve_2;
typedef Traits_2::X_monotone_curve_2 X_monotone_curve_2;
typedef Traits_2::Point_2 Point_2t;
typedef Traits_2::CoordNT coordnt;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::Face_handle Face_handle;
// the following type is not copied from the CGAL library example code but
// introduced by me
typedef std::vector<Polygon_with_holes_2> pwh_vec_t;
// the following is an excerpt of my full GerberLayer class,
// that retains only data members which are used in the join()
// member function. These data is therefore local to the class instance.
class GerberLayer
{
public:
GerberLayer();
~GerberLayer();
void join();
pwh_vec_t raw_poly_lis;
pwh_vec_t joined_poly_lis;
Polygon_set_2 Saux;
annotate_vec_t annotate_lis;
polar_vec_t polar_lis;
};
//
// it is not necessary to understand the working of the function
// I deleted all debug and timing output etc. It is just to "showcase" some typical
// operations from the CGAL reg set boolean ops for polygons library from
// Efi Fogel et.al.
//
void GerberLayer::join()
{
Saux.clear();
auto it_annbase = annotate_lis.begin();
annotate_vec_t::iterator itann = annotate_lis.begin();
bool first_block = true;
int cnt = 0;
while (itann != annotate_lis.end()) {
gpolarity akt_polar = itann->polar;
auto itnext = std::find_if(itann, annotate_lis.end(),
[=](auto a) {return a.polar != akt_polar;});
Polygon_set_2 Sblock;
if (first_block) {
if (akt_polar == Dark) {
Saux.join(raw_poly_lis.begin() + (itann - it_annbase),
raw_poly_lis.begin() + (itnext - it_annbase));
}
first_block = false;
} else {
if (akt_polar == Dark) {
Saux.join(raw_poly_lis.begin() + (itann - it_annbase),
raw_poly_lis.begin() + (itnext - it_annbase));
} else {
Polygon_set_2 Saux1;
Saux1.join(raw_poly_lis.begin() + (itann - it_annbase),
raw_poly_lis.begin() + (itnext - it_annbase));
Saux.complement();
pwh_vec_t auxlis;
Saux1.polygons_with_holes(std::back_inserter(auxlis));
Saux.join(auxlis.begin(), auxlis.end());
Saux.complement();
}
}
itann = itnext;
}
ende:
joined_poly_lis.clear();
annotate_lis.clear();
Saux.polygons_with_holes (std::back_inserter (joined_poly_lis));
}
int join_wrapper(GerberLayer* p_layer)
{
p_layer->join();
return 0;
}
// here the parallelism (of the "embarassing kind") occurs:
// for every GerberLayer a dedicated task is started, which calls
// the above GerberLayer::join() function
void Window::do_unify()
{
std::vector<std::future<int>> fivec;
for(int i = 0; i < gerber_layer_manager.num_layers(); ++i) {
GerberLayer* p_layer = gerber_layer_manager.at(i);
fivec.push_back(std::async(join_wrapper, p_layer));
}
int sz = wait_for_all(fivec); // written by me, not shown
}
//以下typedef或多或少是
//CGAL库示例。
typedef CGAL::精确谓词\u精确构造\u内核;
typedef内核::Point_2 Point_2;
typedef内核::Circle_2 Circle_2;
typedef内核::Line_2 Line_2;
typedef CGAL::Gps_圆_段_特征_2特征_2;
typedef CGAL::General_polygon_set_2 polygon_set_2;
typedef Traits_2::General_polygon_2 polygon_2;
typedef Traits_2::一般多边形带孔多边形带孔多边形;
typedef Traits_2::Curve_2 Curve_2;
typedef特征_2::X_单调_曲线_2 X_单调_曲线_2;
typedef Traits_2::Point_2 Point_2t;
typedef-Traits_2::CoordNT-CoordNT;
typedef CGAL::排列2排列2;
typedef排列_2::面_柄面_柄;
//以下类型不是从CGAL库示例代码复制的,而是
//我介绍的
typedef std::vector pwh_vec_t;
//以下是我整个GerberLayer课程的摘录,
//仅保留联接()中使用的数据成员的
//成员函数。因此,这些数据是类实例的本地数据。
GerberLayer类
{
公众:
GerberLayer();
~GerberLayer();
void join();
原始塑料;
普华永道加入保利集团;
多边形集合2;
注释(vec)t注释(lis);;
极坐标向量极坐标;
};
//
//无需了解函数的工作原理
//我删除了所有调试和定时输出等。这只是为了“展示”一些典型的
//来自CGAL reg集合的多边形布尔运算库的操作来自
//Efi Fogel等人。
//
void GerberLayer::join()
{
Saux.clear();
auto it_annbase=注释_lis.begin();
annotate_vec_t::迭代器Itan=annotate_lis.begin();
bool first_block=true;
int-cnt=0;
while(Itan!=注释_lis.end()){
G极性akt_polar=Itan->polar;
auto itnext=std::find_if(Itan,annotate_lis.end(),
[=](自动a){返回a.polar!=akt_polar;});
多边形集合2块;
如果(第一块){
如果(akt_polar==暗){
Saux.join(raw_poly_lis.begin()+(itann-it_annbase),
原始poly_lis.begin()+(itnext-it_annbase));
}
第一块=假;
}否则{
如果(akt_polar==暗){
Saux.join(raw_poly_lis.begin()+(itann-it_annbase),
原始poly_lis.begin()+(itnext-it_annbase));
}否则{
多边形集合2;
Saux1.join(raw_poly_lis.begin()+(itann-it_annbase),
原始poly_lis.begin()+(itnext-it_annbase));
Saux.complement();
公共交通工具;
带孔的多边形(标准::背面插入器(auxlis));
join(auxlis.begin(),auxlis.end());
Saux.complement();
}
}
Itan=itnext;
}
恩德:
已连接的多边形透明();
注释_lis.clear();
带孔的Saux.polygons_(标准:背面插入器(连接的poly_lis));
}
int join_包装(GerberLayer*p_层)
{
p_层->连接();
返回0;
}
//这里出现了平行性(即“禁运类型”):
//对于每个GerberLayer,都会启动一个专用任务,该任务调用
//上面的GerberLayer::join()函数
void Window::do_unified()
{
std::向量fivec;
对于(int i=0;i
有人可能会认为,2)必须是可能的,因为游戏中只有多边形和排列的“不同”实例。但是:可以想象,由于库使用任意精度点(Point_2t
,在我上面的代码中),出于某种实现原因或其他原因,所有点都被插入到类Point_2t的静态列表中,因此相同的点在该列表中只表示一次。因此,不会有“点2t的独立实例”,因此也不会有“多边形2”或“多边形集2”,人们可以告别线程安全
我试图通过谷歌搜索来解决这个问题(我必须承认,不是通过分析库代码),并希望得到一个权威的答案(希望是肯定的,因为这个原始的并行性)
// the following typedefs are more or less standard from the
// CGAL library examples.
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Circle_2 Circle_2;
typedef Kernel::Line_2 Line_2;
typedef CGAL::Gps_circle_segment_traits_2<Kernel> Traits_2;
typedef CGAL::General_polygon_set_2<Traits_2> Polygon_set_2;
typedef Traits_2::General_polygon_2 Polygon_2;
typedef Traits_2::General_polygon_with_holes_2 Polygon_with_holes_2;
typedef Traits_2::Curve_2 Curve_2;
typedef Traits_2::X_monotone_curve_2 X_monotone_curve_2;
typedef Traits_2::Point_2 Point_2t;
typedef Traits_2::CoordNT coordnt;
typedef CGAL::Arrangement_2<Traits_2> Arrangement_2;
typedef Arrangement_2::Face_handle Face_handle;
// the following type is not copied from the CGAL library example code but
// introduced by me
typedef std::vector<Polygon_with_holes_2> pwh_vec_t;
// the following is an excerpt of my full GerberLayer class,
// that retains only data members which are used in the join()
// member function. These data is therefore local to the class instance.
class GerberLayer
{
public:
GerberLayer();
~GerberLayer();
void join();
pwh_vec_t raw_poly_lis;
pwh_vec_t joined_poly_lis;
Polygon_set_2 Saux;
annotate_vec_t annotate_lis;
polar_vec_t polar_lis;
};
//
// it is not necessary to understand the working of the function
// I deleted all debug and timing output etc. It is just to "showcase" some typical
// operations from the CGAL reg set boolean ops for polygons library from
// Efi Fogel et.al.
//
void GerberLayer::join()
{
Saux.clear();
auto it_annbase = annotate_lis.begin();
annotate_vec_t::iterator itann = annotate_lis.begin();
bool first_block = true;
int cnt = 0;
while (itann != annotate_lis.end()) {
gpolarity akt_polar = itann->polar;
auto itnext = std::find_if(itann, annotate_lis.end(),
[=](auto a) {return a.polar != akt_polar;});
Polygon_set_2 Sblock;
if (first_block) {
if (akt_polar == Dark) {
Saux.join(raw_poly_lis.begin() + (itann - it_annbase),
raw_poly_lis.begin() + (itnext - it_annbase));
}
first_block = false;
} else {
if (akt_polar == Dark) {
Saux.join(raw_poly_lis.begin() + (itann - it_annbase),
raw_poly_lis.begin() + (itnext - it_annbase));
} else {
Polygon_set_2 Saux1;
Saux1.join(raw_poly_lis.begin() + (itann - it_annbase),
raw_poly_lis.begin() + (itnext - it_annbase));
Saux.complement();
pwh_vec_t auxlis;
Saux1.polygons_with_holes(std::back_inserter(auxlis));
Saux.join(auxlis.begin(), auxlis.end());
Saux.complement();
}
}
itann = itnext;
}
ende:
joined_poly_lis.clear();
annotate_lis.clear();
Saux.polygons_with_holes (std::back_inserter (joined_poly_lis));
}
int join_wrapper(GerberLayer* p_layer)
{
p_layer->join();
return 0;
}
// here the parallelism (of the "embarassing kind") occurs:
// for every GerberLayer a dedicated task is started, which calls
// the above GerberLayer::join() function
void Window::do_unify()
{
std::vector<std::future<int>> fivec;
for(int i = 0; i < gerber_layer_manager.num_layers(); ++i) {
GerberLayer* p_layer = gerber_layer_manager.at(i);
fivec.push_back(std::async(join_wrapper, p_layer));
}
int sz = wait_for_all(fivec); // written by me, not shown
}