Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/60.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 当最小分配对齐为16字节时,如何进行24字节大小的分配?_C++_C_Memory Management_Malloc_Jemalloc - Fatal编程技术网

C++ 当最小分配对齐为16字节时,如何进行24字节大小的分配?

C++ 当最小分配对齐为16字节时,如何进行24字节大小的分配?,c++,c,memory-management,malloc,jemalloc,C++,C,Memory Management,Malloc,Jemalloc,我的应用程序进行了大量正好24字节的分配,但我使用的是第三方库,它要求分配器提供至少16字节的对齐 因此,如果我编译配置为8字节对齐的jemalloc(——使用lg quantum=3),我会得到一个24字节的分配,但我的第三方库失败 如果我编译jemalloc配置为16字节对齐(——使用lg quantum=4),我的malloc((大小)24)调用分配32字节。这使内存使用率增加了33.3%。但是,我需要常规的malloc((size_t)24)调用来分配16字节对齐(因此是32字节),这样

我的应用程序进行了大量正好24字节的分配,但我使用的是第三方库,它要求分配器提供至少16字节的对齐

因此,如果我编译配置为8字节对齐的
jemalloc
——使用lg quantum=3
),我会得到一个24字节的分配,但我的第三方库失败

如果我编译
jemalloc
配置为16字节对齐(
——使用lg quantum=4
),我的
malloc((大小)24)
调用分配32字节。这使内存使用率增加了33.3%。但是,我需要常规的
malloc((size_t)24)
调用来分配16字节对齐(因此是32字节),这样我的第三方库才能工作

如何从应用程序中分配24字节块(8字节对齐)以高效使用内存


我尝试了
aligned\u alloc(8,24)
,但它仍然分配32个字节,16个字节对齐。

如果您正在进行大量正好24个字节的分配,并且这些分配的内存效率令人担忧,那么您根本不应该直接使用
malloc
。您应该使用大小为24字节的池分配器

池分配器从堆中分配一大块内存,然后将其划分为指定大小的固定大小的块。这样,不仅可以避免对齐开销,还可以避免堆用于跟踪空闲数据块的信息开销。您还可以帮助避免由如此微小的分配造成的碎片。释放这些分配相当快(就像释放它们一样)。等等


使用池分配器,您应该能够准确地分配所需的资源,而不会干扰正在使用的库。您可以为10000个24字节的块分配一块内存,唯一的开销是跟踪空闲块所需的簿记(如果您聪明的话,这些空闲块本身大部分都可以使用)。

如果您正在进行大量正好24字节的分配,并且这些分配的内存效率令人担忧,您根本不应该直接使用
malloc
。您应该使用大小为24字节的池分配器

池分配器从堆中分配一大块内存,然后将其划分为指定大小的固定大小的块。这样,不仅可以避免对齐开销,还可以避免堆用于跟踪空闲数据块的信息开销。您还可以帮助避免由如此微小的分配造成的碎片。释放这些分配相当快(就像释放它们一样)。等等


使用池分配器,您应该能够准确地分配所需的资源,而不会干扰正在使用的库。您可以为10000个24字节的块分配一块内存,唯一的开销是跟踪空闲块所需的簿记(如果您聪明的话,这些空闲块本身大部分都可以使用)。

您的应用程序分配了大量24字节的对象,您希望结合以下目标:

  • 在16字节边界上对齐每个24字节对象,可能是为了用SIMD指令读取其内容
  • 使用尽可能少的内存,理想情况下每个对象仅使用24字节
这些目标是不兼容的:如果对象需要16字节对齐,则它们之间必须至少相隔32字节,而不管您如何分配内存

C库
malloc()
可能已经在您的系统上强制执行了16字节对齐(对于SIMD兼容数据,这是64位系统的一个常见要求),但可以使用块末尾的8字节空闲空间来保存自己的簿记数据
jemalloc()
当然可以。因此,开销不是浪费的,而是分配算法固有的

由于对齐约束,在池中分配对象无助于打包。它可能更高效,但现代的
malloc()
实现非常高效,有些实现确实使用基于线程的池(例如
tcmalloc()

设计自己的分配方案很棘手,而且容易出错,链接自定义的
malloc()
实现也很重要,因为它可能会导致C库函数自己使用
malloc()
时出现问题。我强烈建议不要使用这些方法,除非您非常精通C语言,并且对您的系统有很好的了解

改进打包有一个可能的方向:如果您还分配了许多8字节对象,那么您可以将它们交错在32字节块的组合池中,使用前24字节表示在16字节边界上对齐的24字节对象,其余8字节表示在8字节边界上对齐的单独8字节对象

另一种方法是使用相同的索引将24字节对象的存储拆分为16字节部分的数组和另一个8字节部分的数组,以访问相同逻辑对象的部分。如果您知道要分配的此类对象的最大数量,那么这是一个可行的解决方案。您可以使用索引值而不是指针来访问部件。这可能需要对代码进行大量修改

在当前系统中,内存非常便宜且丰富。除非针对现有部署的嵌入式系统,否则为应用程序指定更多RAM是一种简单而有效的方法

这是一个24字节对象的池分配器,开销非常小。请尝试查看是否使用更少的内存并获得更好的性能:

#包括
#包括
#包括
#包括
#包括
类型定义结构池链接{
struct pool\u link\u t*next;//自由列表的通用链接
}池链接;
类型定义结构池页面{
struct pool_block_t*head;//指向每个页面开头的块的指针
}游泳池第页;
类型定义结构池块池块;
结构池\u块\u t{
池_座_t*h