M XNet c ++ Утечка памяти при извлечении памяти - PullRequest
0 голосов
/ 31 января 2020

Мой код - это сервер извлечения функций, который должен быть многопоточным. Он использует M XNET C ++ с поддержкой GPU (cuda).

Я собрал библиотеку m xnet и провел несколько тестов, и все заработало.

Теперь возникает проблема ... Когда я писал код сервера, всякий раз, когда я выполняю извлечение функций, потребление ОЗУ графического процессора увеличивается до достижения максимума, и код падает.

мой код:

Context global_ctx(kGPU, 0);


FeatureExtractor *fe = new FeatureExtractor();

int sockfd, newsockfd, portno, pid;
socklen_t clilen;

struct sockaddr_in serv_addr, cli_addr;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
    error("ERROR opening socket");

bzero((char *) &serv_addr, sizeof(serv_addr));
portno = atoi("2200");
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);

if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
    error("ERROR on binding");

listen(sockfd,5);
clilen = sizeof(cli_addr);

int count =0;

while (1)
{
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0)
        error("ERROR on accept");

    pthread_t thread;
    ThreadData data;
    data.fe = fe;
    data.newsockfd = newsockfd;
    data.threadNumber = count;

    count ++;

    pthread_create(&thread, NULL, testThread, (void*)&data);

}

close(sockfd);

Функция потока testThread:

QElapsedTimer timer;
ThreadData data = *((ThreadData*) arg);
int newsockfd = data.newsockfd;
FeatureExtractor *fe = data.fe;
int count = data.threadNumber;

int n;
char msgLen[10];
unsigned char *buffer;

bzero(msgLen, 10);

n = read(newsockfd,msgLen,10);
if (n < 0)
    error("ERROR reading from socket");
int size = stoi(msgLen);
int chunk = 1024;

n = write(newsockfd,msgLen,10);
if (n < 0)
    error("ERROR writing to socket");

buffer = new unsigned char [size];
int current=0;
while(current<size)
{
    n = read(newsockfd,(unsigned char*)(buffer)+current, min(chunk,size-current));
    if (n <= 0)
    {
        cout<<"ERROR reading from socket when receiving"<<endl;
        break;
    }
    current+=n;
}

vector<unsigned char> imageBuffer(buffer, buffer + size);

Mat frame = imdecode(imageBuffer,1);

timer.start();
auto data1 = Data2NDArray(frame);
vector<float> test = fe->Extract(data1);

cout<<"done "<<count<<" in: "<<timer.elapsed()<<" ms"<<endl;

close(newsockfd);
pthread_exit(NULL);

Экстрактор функций определен как:

class FeatureExtractor {
    map<string, NDArray> args_map;
    map<string, NDArray> aux_map;
    Symbol net;
    Executor *executor;
    void GetFeatureSymbol()
    {
        QElapsedTimer timer;
        timer.start();
        net = Symbol::Load("./model/model-symbol.json").GetInternals()["fc1_output"];
        cout<<"Time To Load: "<<timer.elapsed()<<endl;
    }

    void LoadParameters() {
        map<string, NDArray> paramters;
        NDArray::Load("./model/model-0001.params", 0, &paramters);
        for (const auto &k : paramters)
        {
            if (k.first.substr(0, 4) == "aux:") {
                auto name = k.first.substr(4, k.first.size() - 4);
                aux_map[name] = k.second.Copy(global_ctx);
            }
            if (k.first.substr(0, 4) == "arg:") {
                auto name = k.first.substr(4, k.first.size() - 4);
                args_map[name] = k.second.Copy(global_ctx);
            }
        }
        NDArray::WaitAll();
    }

public:
    FeatureExtractor()
    {
        GetFeatureSymbol();
        LoadParameters();
    }

    vector<float> Extract(NDArray data) {

        args_map["data"] = data;
        executor = net.SimpleBind(global_ctx, args_map, map<string, NDArray>(),
                                  map<string, OpReqType>(), aux_map);
        executor->Forward(false);

        auto array = executor->outputs[0].Copy(Context(kCPU, 0));
        NDArray::WaitAll();
        array = array.Reshape({1, 512});


        double mod = 0.0;

        for (size_t i = 0; i < 512; ++i)
        {
            mod += array.At(0,i) * array.At(0,i);
        }

        double mag = std::sqrt(mod);


        vector<float> output;
        for (size_t i = 0; i < 512; ++i)
        {
            output.push_back(array.At(0, i) / mag);
        }

        executor->Backward();
        delete executor;
        return output;
    }
};

Я перешел в режим отладки и обнаружил, что в этой строке происходит увеличение памяти графического процессора

executor = net.SimpleBind(global_ctx, args_map, map<string, NDArray>(),
                              map<string, OpReqType>(), aux_map);

Я удаляю исполнителя, но память (показанная в nvidia-smi) не освобождается. Я пропустил немного свободного, немного памяти, которая должна быть очищена на GPU ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...