【问题标题】:Share CGAL's geometry between processes in C++在 C++ 中的进程之间共享 CGAL 的几何图形
【发布时间】:2012-09-29 22:21:04
【问题描述】:

我正在寻找在进程之间发送 CGAL 几何的最快方法 (C++)。假设我们有 2 个进程 - A 和 B。进程 A 正在生成几何图形,进程 B 正在显示它。我想以最快的方式连接它们。几何形状为CGALs多面体类型。

我知道我可以使用共享内存,但是我遇到了一些问题:

  1. 当我想将几何图形从进程 A 复制到共享内存时,我可以使用流式传输多面体到/从 OFF 格式,但我对此不感兴趣,因为转换到这种格式对于我的目的来说太慢了。
  2. 我可以创建共享内存并使用“placement new”在共享内存中创建我的对象并克服流式传输和转换的开销,但是我无法通过内部多面体函数进一步控制内存分配。 (例如,当使用 Polyhedron_incremental_builder_3 添加新顶点时,我无法指定它应该放置在内存中的确切位置 - 我可以调用 B.add_vertex( Point( 0, 0, 0)); 并且在该方法中处理内存分配内部)

有没有办法在共享内存的特定位置创建对象并确保它及其动态结构将“存在”在该内存中?

或者也许还有另一种在两个进程之间共享动态数据(即半边结构)的快速方法?

【问题讨论】:

  • 我认为您可以实例化 HalfedgeDS 类并提供您的自定义分配器作为模板参数。据我所知,也可以用你自己的重新绑定默认的CGAL_ALLOCATOR(int)。不幸的是,我对此没有更多的了解。如果有人能在这件事上提供更多信息,我将不胜感激..

标签: c++ geometry ipc shared-memory cgal


【解决方案1】:

我无法通过内部多面体进一步控制内存分配 功能。

你确实有控制权。

参考手册说:

Polygon_2 类实现了多边形。 Polygon_2 由特征参数化 类和容器类。后者可以是任何满足的类 STL 容器的要求。它默认为向量 类。

除了为多边形本身使用placement new,您还需要一个可以放置在共享内存中的容器。您可以尝试使用boost::interprocess::vector,或者滚动您自己的容器类。

如果您使用boost::interprocess::vector,您将需要为其创建一个包装类,因为与 STL 容器不同,它的构造函数需要一个分配器objectPolygon_2 将无法正确构造它。因此,您必须从某种全局变量中获取共享内存分配器对象。例如:

using namespace boost::interprocess;
typedef allocator<int, managed_shared_memory::segment_manager>  ShmemAllocator;
ShmemAllocator some_global_shmem_allocator;
template <typename T>
class my_shared_memory_vector : vector<T, ShmemAllocator>
{
public:
  my_shared_memory_vector() : vector(some_global_shmem_allocator) {}
};

免责声明:我自己实际上并没有做过任何这些。如果您的计算机因此而着火并且您的房子被烧毁,请不要让我负责。明智的做法是仔细检查(通过查看 GCAL 源代码)Polygon_2 分配的任何内存实际上是由容器管理的。

编辑:我误读了这个问题,它询问的是多面体,而不是多边形。请参阅下面的评论。

【讨论】:

  • 您好,我也对这个主题感兴趣,但您的解决方案仅适用于 2D 几何处理。你知道任何其他适用于 3D 的解决方案吗?
  • 我想我误读了原始问题(多边形而不是多面体)。 CGAL::Polyhedron_3 实际上与Polygon_2 有点相似,因为它也使用用户提供的容器,但是,对于Polyhedron_3,它是一个相当复杂的HalfedgeDS 模板而不是简单的容器。该库提供HalfedgeDS 的类向量和类列表实现。应该可以实现和使用基于共享内存的HalfedgeDS 变体,但是,它可能非常重要。
  • 感谢您的回答。如果有人可以帮助我解决这个问题,那就太好了:)
【解决方案2】:

当然,最明显的做法是使用线程而不是进程。这将毫不费力地解决整个问题。

除此之外,除了破解编译器的运行时库来替换其内存管理之外,您实际上可以为一个类覆盖“operator new”,和/或您可以提供一个全局的。这将使您可以用自己的内存分配代码替换“新”调用。您可以使用在进行 CGAL 调用之前设置的全局标志并在之后重置,以告诉内存分配器您要使用哪个内存堆(您显然必须对共享内存进行某种形式的堆管理)。

当然,覆盖 new 运算符仅适用于“新”调用。任何被分配的东西,例如通过 malloc() 或某些系统调用不会通过您的代码。您可以尝试提供自己的 malloc() 和 free() 调用(包含在目标文件中的函数优先于库中的函数)以查看这是否可行,但这些可能必须处理操作系统以进行内存管理因为你失去了库函数。肯定会很乱。

【讨论】:

  • 使用线程而不是进程并不总是可能或最好的解决方案,例如查看 chrome。每个选项卡都使用不同的进程,并且它们都使用相同的全局设置和插件。您可以对此争论不休,但它提供了相当好的稳定性,并且可以让您轻松完成与编写线程安全代码有关的任何事情。
  • @user1708860 您忽略了硬件隔离(UNIX 进程)需要付出巨大(或至少不平凡)代价的现实。如果您什么都不分享(理想适用于 Chrome),那么它就非常低。如果您像 OP 所希望的那样共享很多内容,那么通常使用线程可以更好地解决这个问题。
  • 请注意,这个答案不符合假设。在我的情况下,不可能使用线程,因为进程 B 是现有应用程序,进程 A 是我的应用程序。当然,在这种情况下,可能会有例外情况允许我的应用程序成为 B 的插件并因此使用线程,但目前这不是我想要的。
猜你喜欢
  • 2021-06-15
  • 2019-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多