【问题标题】:Allocating aligned memory for larger arrays为更大的数组分配对齐的内存
【发布时间】:2017-07-21 04:24:44
【问题描述】:

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

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

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

【问题讨论】:

  • 不到 10MB。您的系统中有多少(虚拟?)内存?系统能否保证它可以分配一块连续的内存(这可能是您遇到的问题)?
  • 哦,你检查分配函数是否返回空指针?
  • 我有 12GB 内存。对不起,我需要超过 10MB。它不是2000 * 1300。它的 2000*1300*17*17。如果我使用 new 它工作正常并且没有问题。然而,内存使用量在 11.9 左右达到峰值。在高级设置中显示“所有驱动器的总页面文件大小为 15247MB”,这是系统管理的仅驱动器 C
  • 是的,它返回一个空指针。谢谢你的提示。我会修改问题。
  • SSE/AVX 需要对齐 32?你能把它放在问题中吗?

标签: c++ memory memory-alignment avx


【解决方案1】:

关于内存分配:

我似乎实际上是在尝试分配 2000*1300*17*17*4 32 bytes 元素。这意味着您尝试分配 96 GB,而您的系统只有 12 GB 内存。

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

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

无论如何,由于您的磁盘比 RAM 慢 方式,您将有巨大的性能损失。这太严重了,使用 AVX 可能根本不会加速任何事情。

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

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

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

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

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

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

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

在这种情况下,您可能还想问另一个关于如何减少内存使用的问题,并提供有关您正在做什么的更多信息。

【讨论】:

    猜你喜欢
    • 2011-11-28
    • 2021-12-29
    • 2014-02-28
    • 1970-01-01
    • 2011-04-29
    • 2012-10-08
    • 2012-12-04
    相关资源
    最近更新 更多