串行分配器/解除分配器

Serial allocators/deallocators

本文关键字:分配器      更新时间:2023-10-16

我有一个代码,其中包含大量的malloc s和设备特定的API mallocs(我在GPU上编程,所以cudaMalloc)。

基本上,我的代码开头的末尾是分配调用的大杂烩,而我的结束部分是deallocation调用。

由于我已经将全局数据封装在结构中,所以释放相当长,但至少我可以将它们分解为一个单独的函数。另一方面,我想要一个更短的解决方案。此外,如果我忘记在全局分配器函数中显式写入释放,那么自动释放程序将降低内存泄漏的风险。

我想知道是否可以编写某种模板化的类包装器,允许我在malloc/cudaMalloc过程中"注册"变量,然后在模拟结束时进行基于大规模循环的解除分配(注销)。需要明确的是,我不想键入单独的解除分配(free/cudaFree s),因为这也是长时间的,也是不希望的,并且假设在设备模拟完成并且main终止之前,我注册的任何东西都不会被解除分配。

这里的一个好处是,如果我注册了一个新的模拟持续时间变量,它将自动解除分配,所以我不会忘记解除分配并造成内存泄漏。

这样的包装物可能吗?

你会建议这样做吗?

如果是,如何?

提前感谢!

一个想法:

创建两个函数,一个分配内存并在将它们注册到已分配指针的"列表"中后提供有效指针的函数。在第二种方法中,循环此列表并解除分配所有指针:

// ask for new allocated pointer that will be registered automatically in list of pointers.
pointer1 = allocatePointer(size, listOfPointers);
pointer2 = allocatePointer(size, listOfPointers);
...
// deallocate all pointers
deallocatePointers(listOfPointers);

甚至,根据您的模拟范围,您可以使用不同的listOfPointers

listOfPointer1 = getNewListOfPointers();
listOfPointer2 = getNewListOfPointers();
....
p1 = allocatePointer(size, listOfPointer1);
p2 = allocatePointer(size, listOfPointer2);
...
deallocatePointers(listOfPointers1);
...
deallocatePointers(listOfPointers2);

正如他们所说,有很多方法可以剥猫的皮。

我推荐使用thrust的device_vector作为内存管理工具。它抽象了CUDA中的分配、释放和内存。它还允许您访问Thrust提供的所有算法。

我不建议像蒂奥·佩佩建议的那样,随意列出不相关的指针。相反,您应该将相关数据封装到一个类中。即使使用thrust::device_vector,也可能希望将多个相关向量及其操作封装到一个类中。

如果可以的话,最好的选择可能是使用C++boost库中的智能指针。

如果没有,那么在C中,您所能期望的最好的是一个程序设计,它允许您在一个地方编写分配和释放。也许类似以下伪代码:

while(!terminate_program)
{
  switch(state_machine)
  {
    case STATE_PREOPERATIONAL:
      myclass_init(); // only necessary for non-global/static objects
      myclass_mem_manager();
      state_machine = STATE_RUNNING;
    break;
    case STATE_RUNNING:
      myclass_do_stuff();
      ...
    break;
    ...
    case STATE_EXIT:
      myclass_mem_manager();
      terminate_program = true;
    break;
  }

void myclass_init()
{
  ptr_x = NULL; 
  ptr_y = NULL;
  /* Where ptr_x, ptr_y are some of the many objects to allocate/deallocate.
     If ptr is a global/static, (static storage duration) it is 
     already set to NULL automatically and this function isn't 
     necessary */
}
void myclass_mem_manager()
{
  ptr_x = mem_manage (ptr_x, items_x*sizeof(Type_x));
  ptr_y = mem_manage (ptr_y, items_y*sizeof(Type_y));
}

static void* mem_manage (const void* ptr, size_t bytes_n)
{
  if(ptr == NULL)
  {
    ptr = malloc(bytes_n);
    if (ptr == NULL)
    {} // error handling
  }
  else
  {
    free(ptr);
    ptr = NULL;
  }
  return ptr;
}