Утечка памяти C ++ Threading - PullRequest
       57

Утечка памяти C ++ Threading

0 голосов
/ 24 апреля 2020

У меня проблема, вероятно, с утечкой памяти в потоках C ++. Я получаю ошибку времени выполнения с кодом 11. Я пишу алгоритм оптимизации, который направлен на оптимизацию параметров 2D реакторов. Он генерирует экземпляры функции реформирования, которая создает объекты реформатора. Реформаторы имеют 2 разных параметра, которые могут локально отличаться в одном реформинге и передаются в функцию реформинга из основной функции. Чтобы указать, каждый реформатор разделен на определенное количество зон (одинаковые размеры и местоположения в каждом реформаторе), и каждая зона может иметь разные параметры. Следовательно, размер каждого из 2 векторов равен [КОЛИЧЕСТВО РЕФОРМАТОРОВ] * [КОЛИЧЕСТВО ЗОН]. Затем функция реформирования создает объекты сегмента, число которых равно количеству зон.

Я предполагаю, что проблема заключается в том, что потоки пытаются получить доступ к одному и тому же вектору одновременно, и я был бы очень признателен за решение этой проблемы. Вопрос.

Примечания:

  1. Если я изменю основной. cpp, чтобы заменить потоки обычным l oop, ошибки не будет возвращено.
  2. Если я закомментирую метод setProp в функциях set_segments, ошибка не будет возвращена (с потоками).

Здесь настоятельно рекомендуются потоки из-за большого времени вычислений одного реформатора, и у меня есть доступ к многоядерным вычислительным блокам.

Для пояснения я объясню все с минимальным воспроизводимым примером:

input.h

#include <iostream>
#include <fstream>
#include <vector>
#include <thread>
int reactor_no = 2;    // number of reformers
int zones_X = 5;       // number of zones in a single reformer, X direction
int zones_Y = 2;       // number of zones in a single reformer, Y direction
double dim_X = 0.5;    // reactor's length    
double dim_Y = 0.2;    // reactor's height
double wall_t = 0.1;   // thickness of the reactor wall
size_t zones = zones_X * zones_Y;

Reformer.h:

#include "input.h"
class Reformer {
public:
    Reformer() {}
    Reformer(const double& L, const double& Y, const double& wall_t, 
                        const int& zones_X = 1, const int& zones_Y = 1) {
        length_ = L;
        height_ = Y;
        zonesX_ = zones_X;
        zonesY_ = zones_Y;
        wall_thickness_ = wall_t;   

        dx_ = length_ / static_cast<double> (zonesX_);
        dr_ = height_ / static_cast<double> (zonesY_);
    }

private:
    double wall_thickness_;         // wall thickness (m)
    double length_;                 // recactor length (m)
    double height_;                 // reactor height (m) (excluding wall thickness)
    int zonesX_;                    // number of segments in the X direction
    int zonesY_;                    // number of segments in the Y direction 
    double dx_;                     // segment width    (m)
    double dr_;                     // segment height (m)
}

Segment.h:

#include "input.h"
class Segment{
public:
    Segment() : Segment(0, 0) {}

    Segment(int i, int j) {
        i_ = i;
        j_ = j;
    }

    void setXR(const double& dx, const double& dr, const int& SL, const int& SR) {
        x0_ = i_ * dx;
        x1_ = x0_ + dx;

        r0_ = j_ * dr;
        r1_ = r0_ + dr;

        if (i_ == SL - 1) {
            x1_ = length;
        }

        if (j_ == SR - 1) {
            r1_ = radius;
        }   
    }

    void setWall() {
        x0_ = 0;
        x1_ = length;

        r0_ = radius;
        r1_ = radius + wall_t;
    }

    void setProp(const double& por, const double& por_s, const bool& cat) {
        porosity_ = por;
        catalyst_ = cat;
    }
private:
    size_t i_;          //segment column no.
    size_t j_;          //segment row no.

    double x0_;         //beginning of segment - x coordinate (m)
    double x1_;         //ending of segment - x coordinate (m)
    double r0_;         //beginning of segment - r coordinate (m)
    double r1_;         //ending of segment - r coordinate (m)

    int catalyst_;      //1 - catalytic, 0 - non-catalytic
    double porosity_;   //porosity (-)

};

main. cpp:

#include "input.h"
int main() {

    int zones = zones_X * zones_Y;

    size_t pop_size = reactor_no * zones;
    std::vector<int> cat;
    cat.reserve(pop_size);
    std::vector<double> porosity;
    porosity.reserve(pop_size);                // the values in the vectors are not important, therefore I will just fill them with 1s
    for (int i = 0; i < pop_size; i++) {
        cat[i] = 1;
        porosity[i] = 1.0;
    }

    std::vector<std::thread> Ref;
    Ref.reserve(reactor_no);
    for (k = 0; k < reactor_no; k++) {
        Ref.emplace_back(reforming, k, cat, porosity);
    }

    for (auto &X : Ref) { X.join(); }
}

reforming. cpp:

    #include "input.h"

void reforming(const int m, const std::vector<int>& cat_check, const std::vector<double>& por) {                                           
    Reformer reactor(length, radius, wall_t, zonesX, zonesY);

    std::vector<Segment> seg;     // vector holding segment objects                                                                  
    seg.reserve(zones);

    set_segments(seg, reactor, zones, m, por, por_s, cat_check);

}

set_segments функция:

#include "input.h"
void set_segments(std::vector<Segment> &seg, Reformer &reac, const int m, 
                     const std::vector<double> &por, const std::vector<int> &check) {
    int i, j, k, n;

    double dx = dim_X / static_cast<double> (zones_X);
    double dy = dim_Y / static_cast<double> (zones_Y);

    std::vector<Segment*> ptr_seg;
    ptr_seg.reserve(zones);

    k = 0;
    for (i = 0; i < zones_X; i++) {
        for (j = 0; j < zones_Y; j++) {
            n = m * zones + (i * zones_Y + j);
            seg.emplace_back(Segment(i, j));
            seg[k].setProp(por[n], check[n]);
            seg[k].setXR(dx, dy, zones_X, zones_Y);
            k++;
        }
    }

}  

1 Ответ

0 голосов
/ 25 апреля 2020

Добавление std :: ref () к параметрам вызова функции реформирования решило проблему.

for (k = 0; k < spec_max; k++) {
        Ref.emplace_back(reforming, k, std::ref(cat), std::ref(porosity));
}
...