簡體   English   中英

C ++ MPI程序中可能發生內存泄漏?

[英]Possible Memory Leak in C++ MPI Program?

我正在為並行計算類編寫一些C ++ MPI代碼。 我的代碼可以工作,我已經完成了分配,但是代碼占用了我預期的更多內存。 隨着處理器數量的增加,每個節點的內存需求也在迅速增長。 這是我必須編寫的第一個真正的C / C ++或MPI程序,因此我認為我在某處存在某種內存泄漏。 有人可以看一下這段代碼,然后告訴我在哪里嗎? 每當我使用new創建變量時,都會將其刪除,因此我不確定我還要尋找什么。 我想一些問題可能來自我正在創建的對象,但是這些對象的析構函數應該在它們作用域的末尾調用以釋放它們在堆上分配的任何內存嗎? 我來自Java豐富的背景,我的大多數C / C ++都是自學的,因此執行自己的內存管理非常困難。

問題很簡單。 我有一個大小為MSIZE * MSIZE的矩陣(存儲為一維向量)。 每個處理器負責一些連續的數據塊。 然后,我運行500次迭代,其中每個非邊緣元素A[r][c]設置為A[r][c], A[r+1][c], A[r-1][c], A[r][c+1], A[r-1][c-1] 在該迭代的整個更新過程完成之前,不會存儲A[r][c]的新值。 處理器必須將邊界上的值傳達給其他處理器。

這是我的代碼(我認為問題出在這里的某個地方,但是如果您想查看其余代碼(主要是幫助程序和初始化函數),請告訴我,我將其發布):

#include <math.h> 
#include "mpi.h" 
#include <iostream>
#include <float.h>
#include <math.h>
#include <assert.h>
#include <algorithm>
#include <map>
#include <vector>
#include <set>
using namespace std;

#define MSIZE 4000
#define TOTAL_SIZE (MSIZE * MSIZE)
#define NUM_ITERATIONS 500

int myRank;
int numProcs;
int start, end;
int numIncomingMessages;

double startTime;

vector<double> a;

map<int, set<int> > neighborsToNotify;


/*
 * Send the indices that have other processors depending on them to those processors.
 * Once the messages have been sent, receive messages until we've received all the messages
 * we are expecting to receive.
 */
void doCommunication(){
    int messagesReceived = 0;
    map<int, set<int> >::iterator iter;
    for(iter = neighborsToNotify.begin(); iter != neighborsToNotify.end(); iter++){
        int destination = iter->first;
        set<int> indices = iter->second;

        set<int>::iterator setIter;
        for(setIter = indices.begin(); setIter != indices.end(); setIter++){
            double val = a.at(*setIter);
            MPI_Bsend(&val, 1, MPI_DOUBLE, destination, *setIter, MPI_COMM_WORLD);
        }

        MPI_Status s;
        int flag;
        MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &s);
        while(flag){
            double message;
            MPI_Recv(&message, 1, MPI_DOUBLE, s.MPI_SOURCE, s.MPI_TAG, MPI_COMM_WORLD, &s);
            a.at(s.MPI_TAG) = message;
            messagesReceived++;
            MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &flag, &s);
        }

    }

    while(messagesReceived < numIncomingMessages){
        MPI_Status s;
        MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, MPI_COMM_WORLD, &s);
        double message;
        MPI_Recv(&message, 1, MPI_DOUBLE, s.MPI_SOURCE, s.MPI_TAG, MPI_COMM_WORLD, &s);
        a.at(s.MPI_TAG) = message;
        messagesReceived++;
    }
}

/*
 * Perform one timestep of iteration.
 */
void doIteration(){
    int pos;
    vector<double> temp;
    temp.assign(end - start + 1, 0);
    for(pos = start; pos <= end; pos++){
        int i;
        double max;

        if(isEdgeNode(pos))
            continue;

        int dependents[4];
        getDependentsOfPosition(pos, dependents);

        max = a.at(pos);

        for(i = 0; i < 4; i++){
            if(isInvalidPos(dependents[i]))
                continue;

            max = std::max(max, a.at(dependents[i]));
        }

        temp.at(pos - start) = max;
    }

    for(pos = start; pos <= end; pos++){
        if(! isEdgeNode(pos)){
            a.at(pos) = temp.at(pos - start);
        }
    }
}

/*
 * Compute the checksum for this processor
 */
double computeCheck(){
    int pos;
    double sum = 0;
    for(pos = start; pos <= end; pos++){
        sum += a.at(pos) * a.at(pos);
    }
    return sum;
}

int main(int argc, char *argv[]) {
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
    MPI_Comm_size(MPI_COMM_WORLD, &numProcs);

    findStartAndEndPositions();

    initializeArray();

    findDependentElements();

    MPI_Barrier(MPI_COMM_WORLD);

    if(myRank == 0){
        startTime = MPI_Wtime();
    }

    int i;
    for(i = 0; i < NUM_ITERATIONS; i++){
        if(myRank == 0)
            cout << ".";
        doCommunication();
        MPI_Barrier(MPI_COMM_WORLD);
        doIteration();
    }

    double check = computeCheck();
    double receive = 0;

    MPI_Reduce(&check, &receive, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

    if(myRank == 0){
        cout << "n = " << MSIZE << " and p = " << numProcs << "\n";
        cout << "The total time was: " << MPI_Wtime() - startTime << " seconds \n";
        cout << "The checksum was: " << receive << " \n";
    }

    MPI_Finalize();
    return 0;
}

我認為您沒有內存泄漏。 但是您可以使用valgrind進行測試。 請注意,輸出看起來很可怕。

 mpirun -n8 valgrind ./yourProgram

我認為原因是MPI。 您使用緩沖發送,因此每個節點將生成一個自己的緩沖區,您擁有的節點越多,緩沖區就會越多。 為了確保您的算法相對於內存可擴展,請使用無緩沖發送(僅用於調試目的,因為這會降低您的加速速度)。 或者,嘗試僅增加112 MB的矩陣,這實際上並不是並行化的問題。 嘗試找到一些大小,以便使用一個節點的幾乎所有內存。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM