删除[]个性能问题

Ove*_*ain 1 c++ arrays performance memory-management

我编写了一个程序,用于计算流水车间调度问题。

我需要帮助来优化程序中最慢的部分:

首先是数组二维数组分配:

this->_perm = new Chromosome*[f];

//... for (...)

this->_perm[i] = new Chromosome[fM1];
Run Code Online (Sandbox Code Playgroud)

它工作正常,但是当我尝试删除数组时出现问题:

delete [] _perm[i];
Run Code Online (Sandbox Code Playgroud)

执行上面的行需要花费极长时间。Chromosome是大约30万个元素的数组-分配它需要不到一秒钟的时间,而删除要花一分钟多的时间。

我将对改善删除部分的任何建议表示赞赏。

sbi*_*sbi 5

总的来说,您永远不应该在C ++中手动管理内存。这将导致泄漏,重复删除和各种不便之处。为此使用适当的资源处理类。例如,std::vector您应该使用它来管理动态分配的阵列。


为了解决当前的问题,您首先需要知道做什么delete [] _perm[i]:它Chromosome为该数组中的每个对象调用析构函数,然后释放内存。现在,您可以循环执行此操作,这意味着它将调用所有 Chromosome析构函数并执行f释放。正如在对您的问题的评论中已经提到的那样,析构函数可能Chromosome 是真正的罪魁祸首。尝试对此进行调查。


但是,您可以更改内存处理以提高分配和重新分配的速度。如Nawaz所示,您可以分配一大块内存并使用它。我将使用a std::vector作为缓冲区:

void f(std::size_t row, std::size_t col)
{
  int sizeMemory = sizeof(Chromosome) * row * col;
  std::vector<unsigned char> buffer(sizeMemory); //allocation of memory at once!

  vector<Chromosome*> chromosomes(row);

  // use algorithm as shown by Nawaz
  std::size_t j = 0 ;
  for(std::size_t i = 0 ; i < row ; i++ )
  {
      //...
  }

  make_baby(chromosomes); //use chromosomes

  in_place_destruct(chromosomes.begin(), chromosomes.end());

  // automatic freeing of memory holding pointers in chromosomes
  // automatic freeing of buffer memory
}

template< typename InpIt >
void in_place_destruct(InpIt begin, InpIt end)
{
  typedef std::iterator_traits<InpIt>::value_type value_type; // to call dtor
  while(begin != end)
    (begin++)->~value_type(); // call dtor
}
Run Code Online (Sandbox Code Playgroud)

但是,尽管通过std::vector 这种方式处理所有内存仍然不是完全异常安全的,因为它需要Chromosome显式调用析构函数。(如果make_baby()引发异常,则该函数f()将提前中止。尽管向量的析构函数将删除其内容,但其中的一个仅包含指针,而另一个则将其内容视为原始内存。没有任何防护措施来监视在其中创建的实际对象原始内存。)


我看到的最好的解决方案是使用包装在类中的一维数组,该类允许二维访问该数组中的元素。(毕竟,在当前硬件上,内存一维的,因此系统已经在执行此操作。)以下是其示意图:

class chromosome_matrix {
public:
  chromosome_matrix(std::size_t row, std::size_t col)
   : row_(row), col_(col), data_(row*col)
  {
    // data_ contains row*col constructed Chromosome objects
  }

  // note needed, compiler generated dtor will do the right thing
  //~chromosome_matrix()

   // these rely on pointer arithmetic to access a column
        Chromosome* operator[](std::size_t row)       {return &data_[row*col_];}
  const Chromosome* operator[](std::size_t row) const {return &data_[row*col_];}

private:
  std::size_t row_;
  std::size_t col_;
  std::vector<chromosomes> data_
};

void f(std::size_t row, std::size_t col)
{
  chromosome_matrix cm(row, col);

  Chromosome* column = ch[0];          // get a whole column
  Chromosome& chromosome1 = column[0]; // get one object

  Chromosome& chromosome2 = cm[1][2];  // access object directly

  // make baby
}
Run Code Online (Sandbox Code Playgroud)