1. 程式人生 > >CUDA進階第六篇-GPU資源(視訊記憶體、控制代碼等)管理

CUDA進階第六篇-GPU資源(視訊記憶體、控制代碼等)管理

最近在加速一個影象演算法,符合《CUDA進階第五篇-如何估算出程式的GPU加速比》中的第二種情況,程式由核函式和GPU API實現,但是資源管理特別差,視訊記憶體和控制代碼在程式中使用時才申請。每次函式執行都要申請和釋放一遍,非常耗費時間。

優化方案一:C++重構

我想到的第一個方案,就是C++重構,將所有的視訊記憶體和控制代碼定義為成員變數,在建構函式中申請,解構函式中釋放。難度比較低,但是工作量比較大,因為不同變數申請的顯示卡大小不一樣,輸入影象的大小是不一定的,所以對於每一個變數,必須申請足夠大的記憶體,而且這種情況下,如果發生視訊記憶體越界,則很難定位。而且引數名非常亂,著實費了一些勁才重構完。

優化方案二

因為這個演算法中變數比較多,重構完後,輸入大影象果然出現視訊記憶體越界問題……真的是非常懶得去定位。某天靈光突現,可以用Tensorflow裡的視訊記憶體管理方式進行重構啊,先申請一塊非常大的視訊記憶體,程式中需要的時候直接分配即可。這樣可以最大程度上的少修改原始碼,並且可以有效的解決大影象情況容易出現的視訊記憶體越界問題。詳細程式碼如下。

class MemoryManagement
{
public:
    MemoryManagement(int workspace_total_size)
    {
        workspace_total_size_ = workspace_total_size;
        CUDA_CHECK(cudaMalloc(&workspace_, workspace_total_size_));

        init();
    }
    ~MemoryManagement()
    {
        CUDA_CHECK(cudaFree(workspace_));
    }

    void AllocateMemory(void **ptr, int size)
    {
        int cache_line_size = 4;
        int tmp_size = (size + cache_line_size) / cache_line_size * cache_line_size;
        workspace_used_size_ += tmp_size;

        assert(workspace_used_size_ <= workspace_total_size_);

        *ptr = (void*)workspace_ptr_;
        workspace_ptr_ += size;
    }

    void Reset()
    {
        init();
    }

protected:
    char *workspace_;
    char *workspace_ptr_;
    int workspace_total_size_;
    int workspace_used_size_;

    void init()
    {
        CUDA_CHECK(cudaMemset(workspace_, 0, workspace_total_size_));
        workspace_ptr_ = workspace_;
        workspace_used_size_ = 0;
    }
};

私人接各種CUDA相關外包(除錯、優化、開發影象演算法等),有意向請聯絡,加好友時請註明