有效地使用多个分配器
Using multiple allocators efficiently
我一直在研究将我的分配方法从简化重载new转换为通过代码库使用多个分配器。但是,如何有效地使用多个分配器?通过我的研究,我能设计的唯一方法就是让分配器成为全局分配器。尽管如此,这似乎有问题,因为使用许多全局变量通常是一个"坏主意"。
我想知道如何有效地使用多个分配器。例如,我可能有一个分配器只用于特定的子系统,而另一个分配器用于不同的子系统。我不确定是否唯一的方法是使用多个全局分配器,所以我希望有更好的见解和设计。
在C++2003中,分配器模型被破坏,并且没有真正合适的解决方案。对于C++2011,分配器模型是固定的,您可以拥有每个实例的分配器,这些分配器向下传播到包含的对象(当然,除非您选择替换它们)。通常,为了使其有用,您可能希望使用动态多态分配器类型,而默认的std::allocator<T>
不需要是这种类型(通常我希望它不会是动态多态的,尽管这可能是更好的实现选择)。然而,标准C++库中几乎所有进行内存分配的类都是以分配器类型为模板参数的模板(例如,IOStreams是一个例外,但通常它们不会分配任何有趣的内存量来保证添加分配器支持)。
在您的一些评论中,您坚持分配器实际上需要是全局的:这绝对是不正确的。每个感知分配器的类型都存储给定分配器的一个副本(至少,如果它有任何实例级数据;如果没有,则没有任何内容可存储,例如,默认分配器使用operator new()
和operator delete()
的情况)。这实际上意味着,只要有任何活动分配器在使用,给对象的分配机制就需要保持不变。这可以使用全局对象来完成,但也可以使用引用计数或将分配器与包含所有对象的对象相关联来完成。例如,如果每个"文档"(想想XML、Excel、Pages,无论什么结构的文件)都将分配器传递给其成员,则分配器可以作为文档的成员存在,并且在文档的所有内容都被销毁后,当文档被销毁时,分配器就会被销毁。分配器模型的这一部分应该与C++2011之前的类一起使用,只要它们也接受分配器参数即可。然而,在C++2011之前的类中,分配器不会传递给包含的对象。例如,如果为std::vector<std::string>
提供分配器,则C++2011版本将使用为std::vector<std::string>
提供的分配器创建std::string
s,该分配器经过适当转换以处理std::string
s。这在C++2011之前的分配器中不会发生。
要在子系统中实际使用分配器,您需要有效地传递它们,要么显式地将其作为函数和/或类的参数,要么通过充当上下文的分配器感知对象隐式地传递。例如,如果使用任何标准容器作为传递的上下文的[一部分],则可以使用其get_allocator()
方法获得所使用的分配器。
您可以使用new
放置。这既可以用于指定内存区域,也可以用于重载类型的static void* operator new(ARGS)
。如果效率很重要,而你的问题又很棘手,那么全球化是不必要的,这真的是个坏主意。当然,您需要保留一个或多个分配器。
你能做的最好的事情就是了解你的问题,并根据程序中的模式和实际使用情况为分配器创建策略。通用malloc
非常擅长它所做的事情,所以总是把它作为一个基线来衡量。如果您不知道自己的使用模式,您的分配器可能会比malloc
慢。
还要记住,除非您为标准容器使用全局或线程本地和自定义分配器,否则您使用的这些类型将失去与标准容器的兼容性——这在许多情况下很快就会失效。另一种选择是编写自己的分配器和容器。
多个分配器的一些用途包括减少CPU使用、减少碎片和减少缓存未命中。因此,解决方案实际上取决于您的分配瓶颈是什么类型和在哪里
通过为活动线程提供无锁定堆,消除同步,可以提高CPU使用率。这可以在具有线程本地存储的内存分配器中完成。
通过从不同的堆中分配具有不同寿命的分配,碎片化将得到改善——将后台IO从用户的活动任务中分配到一个单独的堆中,将确保两者不会混淆。这很可能是通过为堆创建一个堆栈来实现的,当您处于不同的功能范围时,可以进行推送/弹出操作。
缓存未命中将通过将系统内的分配保持在一起而得到改善。四叉树/八叉树分配来自它们自己的堆将保证视图截头查询中存在局部性。最好通过重载特定类的操作符new和操作符delete(OctreeNode)来实现这一点。
- 有效地使用std::unordered_map来插入或增加键的值
- 如何有效地在 std::vector 中插入一对?
- 有效地计算多维数组的累积和?
- 如何有效地计算将单位立方体映射到自身的反射和旋转?
- 有效地将大数存储为 2 的幂用于路径问题
- 如何在C++中写入 1000 个文件时有效地缓冲
- 如何有效地找到数组中三元组和的最小差异?
- 如何在C++中有效地将数字值重新分配给字符数组
- C++有效地找到向量中第一个最接近的匹配值?
- 如何有效地操作满足给定谓词的向量中的所有项目?
- 有效地将数据加载到 std::vector 中<char>
- 如何在使用 cin 请求 int 时有效地使用户输入万无一失?
- C++:有效地将Sha256摘要放入OpenSSL Bignum?
- 如何有效地收集给定数组中的重复元素?
- 如何有效地修剪和合并四叉树中的节点?
- 可以有效地转换 std::any 与 std::any_cast
- 只需要知道我在c ++中打印模式的方式是否有效,或者有另一种方法可以有效地做到这一点
- 如何使用包含内部类的类实例有效地从内部类访问成员?
- 当表示为对象的一维向量时,有效地旋转 NxM 矩阵 (C++)
- 有效地使用多个分配器