cam*_*ccc 3 c++ optimization memory-management
我有一个 C++ 程序,它使用几个非常大的双精度数组,我想减少该程序的这个特定部分的内存占用。目前,我分配了 100 个,每个可以是 100 Mb。
现在,我确实有一个优势,即这些数组的某些部分最终会在程序执行的后续部分中变得过时,并且几乎不需要在任何时候将其中任何一个数组的全部内容存储在内存中。
我的问题是这样的:
在我使用 new 或 malloc 创建数组后,有什么方法可以告诉操作系统其中的一部分不再需要了吗?我得出的结论是,实现此目的的唯一方法是声明一个指针数组,每个指针都可能指向所需数组的一个块(例如 1Mb),以便不再需要旧的块可以重新用于数组的新位。在我看来,这就像编写一个自定义内存管理器,这看起来确实有点像大锤,这也会对性能造成一些影响
我无法移动数组中的数据,因为这会导致太多线程争用问题。这些数组可以随时被大量线程中的任何一个访问,尽管只有一个线程写入任何给定的数组。
这取决于操作系统。POSIX - 包括 Linux - 具有系统调用madvise来提高内存性能。从手册页:
madvise() 系统调用建议内核如何处理从地址 addr 开始、大小为 length 字节的地址范围内的分页输入/输出。它允许应用程序告诉内核它希望如何使用某些映射或共享内存区域,以便内核可以选择适当的预读和缓存技术。此调用不会影响应用程序的语义(MADV_DONTNEED 情况除外),但可能会影响其性能。内核可以随意忽略该建议。
madvise有关详细信息,请参阅 的手册页。
编辑:显然,上面的描述不够清楚。因此,这里有一些更多细节,其中一些是特定于 Linux 的。
您可以使用mmap分配一块不受任何文件支持的内存块(直接从操作系统而不是 libc)。对于大块内存,malloc做的是完全相同的事情。您必须使用munmap来释放内存 - 无论使用madvise:
void* data = ::mmap(nullptr, size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
// ...
::munmap(data, size);
Run Code Online (Sandbox Code Playgroud)
如果你想删除这个块的某些部分,你可以使用madvise告诉内核这样做:
madvise(static_cast<unsigned char*>(data) + 7 * page_size,
3 * page_size, MADV_DONTNEED);
Run Code Online (Sandbox Code Playgroud)
地址范围仍然有效,但不再受物理 RAM 或存储的支持。如果稍后访问这些页面,内核将动态分配一些新页面并将它们重新初始化为零。请注意,不需要的页面也是进程虚拟内存大小的一部分。可能需要对虚拟内存管理进行一些配置更改,例如激活过度使用。
| 归档时间: |
|
| 查看次数: |
1518 次 |
| 最近记录: |