multithreading - 使用 OpenMP 时发生内存泄漏

标签 multithreading gcc memory-leaks openmp allocator

下面的测试用例在使用 OpenMP 时在“post MT 部分”消息之后的循环中在 32 位机器上运行内存不足(抛出 std::bad_alloc),但是,如果 OpenMP 的 #pragmas 被注释掉,代码运行良好,因此看起来当在并行线程中分配内存时,它没有正确释放,因此我们耗尽了内存。

问题是下面的内存分配和删除代码是否有问题,或者这是 gcc v4.2.2 或 OpenMP 中的错误?我也尝试了 gcc v4.3 并遇到了同样的失败。

int main(int argc, char** argv)
{
    std::cout << "start " << std::endl;

    {
            std::vector<std::vector<int*> > nts(100);
            #pragma omp parallel
            {
                    #pragma omp for
                    for(int begin = 0; begin < int(nts.size()); ++begin) {
                            for(int i = 0; i < 1000000; ++i) {
                                    nts[begin].push_back(new int(5));
                            }
                    }
            }

    std::cout << "  pre delete " << std::endl;
            for(int begin = 0; begin < int(nts.size()); ++begin) {
                    for(int j = 0; j < nts[begin].size(); ++j) {
                            delete nts[begin][j];
                    }
            }
    }
    std::cout << "post MT section" << std::endl;
    {
            std::vector<std::vector<int*> > nts(100);
            int begin, i;
            try {
              for(begin = 0; begin < int(nts.size()); ++begin) {
                    for(i = 0; i < 2000000; ++i) {
                            nts[begin].push_back(new int(5));
                    }
              }
            } catch (std::bad_alloc &e) {
                    std::cout << e.what() << std::endl;
                    std::cout << "begin: " << begin << " i: " << i << std::endl;
                    throw;
            }
            std::cout << "pre delete 1" << std::endl;

            for(int begin = 0; begin < int(nts.size()); ++begin) {
                    for(int j = 0; j < nts[begin].size(); ++j) {
                            delete nts[begin][j];
                    }
            }
    }

    std::cout << "end of prog" << std::endl;

    char c;
    std::cin >> c;

    return 0;
}

最佳答案

将第一个 OpenMP 循环从 1000000 更改为 2000000 将导致相同的错误。这表明内存不足问题与 OpenMP 堆栈限制有关。

尝试在 bash 中将 OpenMP 堆栈限制设置为 unlimit

ulimit -s unlimited

您还可以更改 OpenMP 环境变量 OMP_STACKSIZE 并将其设置为 100MB 或更多。

更新1:我将第一个循环更改为

{
    std::vector<std::vector<int*> > nts(100);
    #pragma omp for schedule(static) ordered
    for(int begin = 0; begin < int(nts.size()); ++begin) {
        for(int i = 0; i < 2000000; ++i) {
            nts[begin].push_back(new int(5));
        }
    }

    std::cout << "  pre delete " << std::endl;
    for(int begin = 0; begin < int(nts.size()); ++begin) {
        for(int j = 0; j < nts[begin].size(); ++j) {
            delete nts[begin][j]
        }
    }
}

然后,我在主线程的 i=1574803 处收到内存错误。

更新 2:如果您使用英特尔编译器,您可以将以下内容添加到代码顶部,它将解决问题(前提是您有足够的内存来承受额外的开销)。

std::cout << "Previous stack size " << kmp_get_stacksize_s() << std::endl;
kmp_set_stacksize_s(1000000000);
std::cout << "Now stack size " << kmp_get_stacksize_s() << std::endl;

更新3:为了完整性,就像另一位成员提到的那样,如果您正在执行一些数值计算,最好在单个new float[1000000]中预先分配所有内容,而不是使用OpenMP来执行1000000 分配。这也适用于分配对象。

关于multithreading - 使用 OpenMP 时发生内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4336492/

相关文章:

c++ - 使用 PBO 上传 OpenGL 纹理?

C: 将 "static const char * const"分配给 "static const char *"

java - 在thread_pool中始终始终搜索特定节点

swift - 委托(delegate)类从未发布

c++ - 如何通过 C++ 检索已提交的内存

java - 如何在另一个线程中启动事务?

c - 什么执行进程和线程生成进程

python - 无法捕获线程程序中的异常

linux - 内核如何决定堆栈大小

c++ - 全局模板函数的问题