2012-02-28 89 views
3

我有一個代碼,其中包含大量的malloc和特定於設備的API malloc(我正在GPU上編程,所以cudaMalloc)。連續分配器/解除分配器

基本上我的代碼開始的結尾是一個分配調用的大雜燴,而我的關閉部分是釋放調用。因爲我已經將我的全局數據封裝在結構中,所以釋放時間很長,但至少我可以將它們分解爲一個單獨的函數。另一方面,我想要一個更短的解決方案。此外,如果我忘記在全局分配器函數中明確寫入釋放,自動釋放器將降低創建內存泄漏的風險。

我想知道是否可以編寫某種模板類包裝,它可以允許我在malloc/cudaMalloc過程中「註冊」變量,然後在模擬結束時執行基於質量循環取消分配(取消註冊)。爲了清楚起見,我不想輸入個別的釋放(free/cudaFree s),因爲這又長又不合要求,並且假設我註冊的任何東西都不會被釋放,直到設備模擬完成並且主要正在終止。

這裏的一個好處是,如果我註冊一個新的模擬持續時間變量,它會自動釋放,所以沒有我忘記釋放它並創建內存泄漏的危險。

這樣的包裝可能嗎?

你會建議嗎?

如果是這樣,怎麼樣?

在此先感謝!

+0

老問題,但CUDA給它一個新的味道。有趣。 – 2012-02-28 07:28:09

+0

你喜歡C++的答案還是你的「C」標籤故意? – harrism 2012-02-28 10:12:05

+0

它應該是C++。最初這個項目是用C語言編寫的,但是我在主機端添加了一些STL的東西,因爲它在我的腦海中提供了更簡潔的打印控制。設備代碼和分配/釋放都是傳統的C,但沒有classes @存在。 – 2012-02-29 13:52:02

回答

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

有很多方法對皮膚一隻貓,因爲他們說。

我會推薦推力的device_vector作爲內存管理工具。它在CUDA中抽象分配,釋放和memcpy。它還使您可以訪問Thrust提供的所有算法。

我不推薦像Tio Pepe推薦的那樣隨機地保存無關指針列表。相反,您應該將相關數據封裝到一個類中。即使您使用thrust::device_vector,也可能希望將多個相關的向量和操作封裝到一個類中。

+0

但是,這是C++?編輯:我現在看到CUDA支持C++,但它本來不是。無論如何,問題是關於C,但是這當然可以忽略OP。 – 2012-02-28 07:27:36

+0

CUDA是C++。它一直支持部分C++(如模板),並逐漸增加了更多完整的支持。我沒有看到任何問題將其限制爲C. – harrism 2012-02-28 09:30:19

+0

也許,但維基百科無論如何都表示「CUDA(具有計算能力1.x)使用​​C語言的無遞歸且無函數指針的子集,再加上一些簡單的擴展。「也許這些簡單的擴展是我不知道的模板。這個問題被標記爲「C」,但正如我所說,這可能是OP的疏忽。 – 2012-02-28 09:33:16

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; 
}