c++ - 为较大的数组分配对齐的内存

标签 c++ memory memory-alignment avx

在我的程序中,我想分配 32 字节 对齐的内存以使用 SSE/AVX。我要分配的数量大约是 2000*1300*17*17*4(大数据集)。我尝试使用函数 _aligned_malloc()_mm_malloc 但对于较大的大小,它不会分配内存并导致访问冲突异常。如果分配的数量很小,比如 512*320*4*17*17(small data set),那么代码可以正常工作。

这里,当为大型数据集分配时,这些函数返回一个空指针。但当输入数据量较小时工作正常。同样在这里,如果我只是使用 new 使用未对齐的内存分配,那么代码也适用于大型数据集。
最后,有人能告诉我为 AVX 使用对齐内存是否有显着的性能提升。

编辑:根据这个 post 进行了一些研究之后它说 new 从空闲存储区分配内存,而 malloc() 从堆分配内存。在这里我超过了最大堆大小,因为 _aligned_malloc() 返回 errno 12 这意味着 ENOMEM 在这种情况下有人可以告诉我解决这个问题的方法吗.

最佳答案

关于内存分配:

看来您实际上是在尝试分配 2000*1300*17*17*4 32 字节 元素。这意味着您正在尝试分配 96 GB,而您的系统只有 12 GB 内存。

由于 new 正在运行,但 malloc 没有运行,看来 您的本地 new 实现似乎能够分配大量的 虚拟内存。 Malloc 从堆中分配,这意味着它通常受限于您拥有的物理内存量。这就是它失败的原因。

由于数据集大于您的主内存,您可能希望使用 mmap 分配内存,它将文件映射到虚拟内存中,使其可以访问就好像它在物理内存(但它只会部分缓存在内存中)。我不确定它是否得到保证,但 mmap 通常对齐最佳页面大小边界(几乎总是 4096 字节)。

无论如何,由于您的磁盘比您的 RAM 慢方式,您将有巨大的性能损失。这非常严重,以至于使用 AVX 可能根本不会加快任何速度。

关于使用未对齐内存的性能损失:

在现代硬件上(我认为从 Intel 的 Haswell 开始)这取决于您的访问模式。未对齐访问在按内存顺序遍历数组时几乎没有性能开销(每个缓存行仍将仅加载一次)。如果您以随机顺序访问它,那么您通常会跨越64 字节缓存行边界。这意味着您的处理器将必须将 2 行加载到缓存中并从缓存中删除 2 行,而不是仅仅一行。虽然在某些情况下这可能是一个严重的问题,但磁盘会减慢速度,以至于您几乎不会注意到这一点。

其他提示(或暗中拍摄):

您给出数组大小的方式 (2000*1300*17*17*4) 表明您使用的是多维数组(例如 auto x = new __m256[2000 ][1300][17][17][4])。所以一些提示:

  • 主要按顺序遍历它
  • 检查它是否稀疏(意味着永远不会访问某些内存)并尽可能缩小它。

您可以尝试展平数组并自己进行更复杂的索引计算,以减少内存需求量。如果您让它完全适合您的 RAM,您就可以开始优化您的代码(使用 AVX 和/或对齐内存)。

“所有驱动器的总分页文件大小为 15247MB” 表明您实际上只使用了 96 GB 的一部分,因此可能有进一步减少使用量的方法.

在这种情况下,您可能还想问另一个问题,了解如何通过更多关于您正在做的事情的信息来减少内存使用量。

关于c++ - 为较大的数组分配对齐的内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42538564/

相关文章:

Javascript 内存节省 - if 语句 var 声明

c - 使用共享内存运行程序时出现问题;有时会出现段错误; shmmax和shmall有关系吗?

linux - 不同缓冲区大小的不同内存对齐方式

c++ - 如何为您自己的类型提供免费的开始/结束功能

c++ - 如何仅用宏生成整数序列?

c++ - 是否可以将 std::move 对象移出函数? (C++11)

c++ - 编译器何时以及为什么会在 malloc/free/new/delete 上将内存初始化为 0xCD、0xDD 等?

c++ - 如何对齐结构数组,每个都需要对齐(SSE)

c++ - 编译器如何知道物理地址的对齐方式?

c++ - 指向具有不同参数的成员函数的指针的容器