有没有好的 C++ 自定义分配器? 最大化参考局部性?

发布于 2024-07-21 05:55:24 字数 173 浏览 3 评论 0原文

我正在运行一个模拟,每个对象有很多初始内存分配。 模拟必须尽可能快地运行,但分配的速度并不重要。 我不关心重新分配。

理想情况下,分配器会将所有内容放置在连续的内存块中。 (我认为这有时被称为竞技场?)

我无法使用展平向量,因为分配的对象是多态的。

我有什么选择?

I am running a simulation with a lot if bunch of initial memory allocations per object. The simulation has to run as quickly as possible, but the speed of allocation is not important. I am not concerned with deallocation.

Ideally, the allocator will place everything in a contiguous block of memory. (I think this is sometimes called an arena?)

I am not able to use a flattened vector because the allocated objects are polymorphic.

What are my options?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

樱娆 2024-07-28 05:55:24

自己做吧。

请参阅我的一个老问题,了解如何开始:

此 C++ 堆栈分配器的改进?

Just make your own.

See an old question of mine to see how you can start:

Improvements for this C++ stack allocator?

迎风吟唱 2024-07-28 05:55:24

由于您不关心取消分配,因此可以使用线性分配器。 预先分配大量内存并存储指向开头的指针。 malloc(x) 将分配指针向前移动 x 个字节并返回指针的旧值,delete(x) 被删除。 正如这里提到的,另一张海报已经有 一个实现

分配被紧密地打包为可能的是,分配速度非常快,并且内存按照分配的顺序返回。 模拟完成后,您只需将分配器的指针重置为内存的开头,并清除从分配器外部到其内部对象的所有指针。

如果您想删除对象,池分配器是一个不错的选择,它比堆更快,但不会将数据打包到内存中那么近,而且速度也不那么快。 使用 boost:pool 来解决这些问题。 如果您有 x 个字节来存储(比如一个关卡)并且您愿意同时扔掉所有字节,那么这对于游戏来说是一个不错的选择。

顺便说一句,如果您对内存性能感兴趣,请参阅 每个程序员应该了解的内存知识 - PDF 。 它涵盖了诸如引用位置及其对性能的影响之类的内容。 具体来说,您可能希望为一起使用的每种类型的对象创建一个池,或者将对象声明为数组结构而不是结构数组

Since you don't care about de-allocation you can use a linear allocator. Allocate a huge amount of memory up front and store a pointer to the start. malloc(x) moves the allocation pointer forward by x bytes and returns the old value of the pointer, delete(x) is stubbed out. As mentioned here, another poster already has an implimentation

Allocations are packed as closely as possible, allocations are incredibly fast and memory is returned in the order allocated. When your simulation is done, you just reset the allocator's pointer to the start of memory and clear any pointers you have from outside the allocator to objects inside of it.

Pool allocators are a great choice if you want to delete objects, faster than a heap but won't pack your data into memory as close and aren't quite as fast. Use boost:pool for those. This is a great choice for games if you have x bytes to store say - a level - and you are willing to throw the whole lot away at the same time.

As an aside, if you are interested in memory performance, see What Every Programmer Should Know About Memory-PDF. It covers things like locality of reference and its effect on performance. Specifically, you might want to create a pool for each type of object that is used together, or declare your objects as a struct of arrays rather than a array of structs

宫墨修音 2024-07-28 05:55:24

固定大小块分配器套件工作得相当好,并且获得了非常有吸引力的许可(MIT)。

The Fixed-Size Block Allocator suite works fairly well, and is very attractively licensed (MIT).

迷雾森÷林ヴ 2024-07-28 05:55:24

通常的技术是固定块分配。 请参阅:Lea罗宾逊诺尔顿格伦沃尔德< /a>.

编辑:如果频繁分配和释放,固定块分配确实会留下间隙。 我参与的一个项目中,一个类可能会分配许多不同大小的子对象,但必须保持它们连续,我们使用了一个简单的内存池:一次分配所有对象内容所需的所有内存,然后使用placement new来放置他们在里面。

如果您事先不知道对象的内容有多大,您可以编写一个按顺序分配内存的池分配器; 即,它保证

Foo *a = new Foo();
Bar *b = new Bar;
b == ((byte *)(a)) + sizeof(Foo);

这将确保对象构造函数中发生的所有分配都是连续的。 当对象被释放时,你会得到很大的、参差不齐的间隙,所以我们必须经常进行碎片整理; 即便如此,净速度增益还是显着的。

The usual technique is fixed-block allocation. See: Lea, Robinson, Knowlton, Grunwald.

Edit: fixed block allocation can indeed leave gaps if there are frequent allocations and deallocations. One on project I worked with where a class might allocate many subobjects of different sizes but had to keep them contiguous, we used a simple memory pool: allocate all the memory needed for all the object's contents at once, and then use placement new to lay them out inside that.

If you don't know in advance how large the object's contents will be, you can write a pooling allocator that allocates memory sequentially; ie, it guarantees

Foo *a = new Foo();
Bar *b = new Bar;
b == ((byte *)(a)) + sizeof(Foo);

This will ensure that all allocations occuring within an object's constructor are contiguous. You'll get big, ragged gaps when the objects are deallocated, so we had to defragment every so often; even so the net speed gain was significant.

酒解孤独 2024-07-28 05:55:24

Dave Hanson 的 C 接口和实现 包含一个非常好的基于 arena 的分配器。 如果内存可用,则不会将元数据与对象一起存储,并且它们是从连续的可用空间中分配的,因此这大约是您所希望的尽可能多的局部性。

Dave Hanson's C Interfaces and Implementations includes a very nice arena-based allocator. If memory serves, no metadata is stored with the objects, and they are allocated from contiguous free space, so this is about as much locality as you can hope for.

白昼 2024-07-28 05:55:24

这是一个相当大的主题,只需查看 wikipedia 即可。
Alexandrescu 书中有一个具体的例子,应该在他的 Loki 库 中实现。 GCC 还附带了 std::allocator 的多种实现,只需查看您的发行版即可。

This is a pretty big subject, just take at wikipedia.
One concrete example was in Alexandrescu book and should be implemented in his Loki library. GCC also comes with several implementations of std::allocator, just look into your distribution.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文