串行分配器/解除分配器

时间:2012-02-28 06:53:55

标签: c++ malloc wrapper cuda

我的代码中包含大量malloc和特定于设备的API malloc(我在GPU上进行编程,因此cudaMalloc)。

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

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

我想知道是否有可能编写某种模板化的类包装器,它允许我在malloc / cudaMalloc进程中“注册”变量,然后在结束时模拟执行基于质量循环的解除分配(注销)。为了清楚起见,我不想输入单独的解除分配(free / cudaFree s),因为这又是漫长且不可取的,并且假设我注册的任何内容都不会被释放直到设备模拟完成且主要终止。

这里的一个好处是,如果我注册一个新的模拟持续时间变量,它将自动解除分配,因此我没有忘记取消分配它并造成内存泄漏的危险。

这样的包装可能吗?

你会建议吗?

若然,怎么样?

提前致谢!

3 个答案:

答案 0 :(得分:3)

一个想法:

创建两个函数,一个分配内存并在分配指针的“列表”中注册后提供有效指针的函数。在第二种方法中,循环此列表并释放所有指针:

// 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);

答案 1 :(得分:1)

正如他们所说,有许多方法可以给猫皮肤。

我建议推力device_vector作为内存管理工具。它在CUDA中抽象分配,释放和memcpy。它还允许您访问Thrust提供的所有算法。

我不建议像Tio Pepe推荐的那样随机保存无关指针列表。相反,您应该将相关数据封装到一个类中。即使您使用thrust::device_vector,您也可能希望将多个相关的向量和操作封装到一个类中。

答案 2 :(得分:0)

最好的选择可能是使用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;
}