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万个元素的数组-分配它需要不到一秒钟的时间,而删除要花一分钟多的时间。
我将对改善删除部分的任何建议表示赞赏。
总的来说,您永远不应该在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)