在使用OpenMP时并行化内存分配和删除是否可行?(C ++)

3
int **something = new int *[N];
for(int n = 0; n < N; n++)
    something[n] = new int[M];

#pragma omp parallel for
for (int n = 0; n < N; n++)
    delete[] something[n];
delete[] something;

我可以像这样并行化删除进程吗?
Linux的OOM killer在经过许多循环后杀死了我的进程。我试图找出内存泄漏的原因,但我找不到答案。我不确定for循环删除进程是否有效。

3
但是为什么呢?并行化这个操作能够节省足够的时间来弥补设置和拆卸的时间吗? - Thomas Matthews
1
你的堆是无锁的吗?如果堆有一个互斥锁,会使操作串行化,这将具有讽刺意味。 - Eljay
1
Linux的OOM killer在执行了相当多次循环后杀死了我的进程。并行化“delete”调用会如何帮助解决这个问题? - Andrew Henle
抱歉我的问题表述不够清晰。我刚在Stack Overflow注册并开始学习编程一个月。我做了一个项目,运行了大约100000个循环,但是程序被杀掉了。所以我试图找出内存泄漏发生的地方,并对代码的这一部分产生了疑问。我不知道并行释放内存并不能真正帮助解决问题。 - Mingi Kim
使用 new 不是好的 C++ 编程风格。为什么不使用标准容器呢?它们更加内存安全。 - Victor Eijkhout
显示剩余2条评论
1个回答

6

这通常没问题。标准的 (g)libc 堆必须是线程安全的;否则,写多线程程序将不可能。在一个线程上分配缓冲区,并在另一个线程上释放也是可以的。

并行化堆分配对速度提升的贡献很少,但我猜你问这个问题并不是因为你想加速(解)分配,而是因为你有一些其他的并行代码同时分配和释放一些缓冲区。

要查找泄漏,请尝试使用 valgrind 运行程序。

此外,在释放大量内存后考虑调用 malloc_trim(0);。这使得 glibc 释放未使用的内存回操作系统,而不是为以后的分配保留所有内存。


2
并行化分配实际上会有所帮助,因为不同的线程具有不同的内存区域。因此,这可以并行化处理。我刚刚测试了一下,在我的系统上发现了4倍的因素。仅并行化解除分配将无济于事,因为每个线程都将竞争锁定到一个区域,其中所有内容都被分配。 - Homer512
1
@Homer512 并行化分配实际上会有所帮助,因为不同的线程具有不同的内存区域。 只有在分配的大小不足以被替换为 mmap() 或者导致重复调用 [s]brk() 来获取更多内存时才有效。这两种情况都需要创建和映射新的虚拟内存页,而这两种操作都无法进行多线程处理。 - Andrew Henle
@AndrewHenle 真的,它取决于大小。 - Homer512
我没想到会有这么多用户这么快地给出反馈,因为我是第一个来到这里的。学到了很多东西,会在调试时尝试你提到的这些方法。 - Mingi Kim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接