全局內存

  • 靜態聲明的全局內存變量聲明在全局作用域,不能在主機端代碼中直接用&取值,所以不能用cudaMemcpy進行內存複製

    __device__ Type deviceData;
    __global__ void kernelFunc() {
        data = ...
    }
    int main() {
        Type hostData;
        cudaMemcpyToSymbol(deviceData,&hostData,sizeof(Type);
        kernelFunc <<<1,1>>>();
        cudaMemcpyFromSymbol(&value,deviceData,sizeof(Type));
    

    }

  • 動態聲明

    __global__ void kernelFunc(Type * deviceData) {
        ...
    }
    int main() {
        Type * deviceData;
        cudaMalloc(&deviceData,nBytes);
        cudaMemcpy(deviceData,hostData,nBytes,cudaMemcpyHostToDevice);
        kernekFunc(deviceData);
        cudaMemcpy(hostData,deviceData,nBytes,cudaMemcpyDeviceToHost);
        cudaFree(deviceData);
    }
    
  • 主機到設備的內存傳輸實際經過兩個步驟:
      Pageable Memory -> Pinned Memory
      Pinned Memory -> device memory
    Pinned Memory是主機中不會被換到虛擬內存中的內存,在數據複製時隱式創建,複製完成後會自動銷燬。爲了提高主機到設備內存複製的速度,可以手動申請一段Pinned Memory,但也必須手動地釋放。

    cudaError_t cudaMallocHost(void **devPtr, size_t count);
    cudaError_t cudaFreeHost(void *ptr);
    
  • 零複製內存是主機上一段Pinned Memory,設備端可以直接通過PCI-E總線訪問並會緩存在Cache中。由於主機和設備地址空間不同,零複製內存在主機上的地址需要進行地址映射後才能在設備端使用

    //零複製內存申請
    cudaError_t cudaHostAlloc(void **pHost, size_t count, unsigned int flags);
    
    //主機到設備的地址映射
    cudaError_t cudaHostGetDevicePointer(void **pDevice, void *pHost, unsigned int flags);
    

    零內存複製的使用注意點:
      只有當計算足夠密集以掩蓋PCI-E總線讀取的延遲時才使用零複製內存
      使用零複製內存時要在主機和設備間進行同步

  • 動態分配的內存可以是linear memory(線性內存不一定是一維的,也可以是二維或三維的)或CUDA arrays,後者主要用於存儲紋理)

    //分配linear memory
    cudaMalloc
    cudaMallocPitch
    cudaMalloc3D
    cudaHostAlloc
    
    //分配CUDA array
    cudaMallocArray
    cudaMalloc3DArray
    
  • cudaMallocPitch一般用於二維線性數組,當width小於k * 128(k爲整數)時,cuda會自動爲每一行填充內存,實際每行的長度通過pitch返回。所以分配的總內存爲height * (width + pitch)

    cudaError_t cudaMallocPitch(void ** devPtr,
                                size_t * pitch,
                                size_t  width,
                                size_t  height) 
    
  • 全局內存傳輸
    這裏寫圖片描述

cudaArray

  • cudaArray是專門用於作爲紋理內存的一種全局內存,對GPU而言只讀,可以是一維,二維或三維的。kernel不能直接訪問cudaArray,需要將紋理對象或紋理引用與cudaArray綁定後,訪問紋理對象或紋理引用
  • 計算能力2.0以上的顯卡架構能夠利用surfaces,在gpu端修改cudaArray

  • 創建CUDAMallocArray

    cudaError_t cudaMallocArray(struct cudaArray ** array,
                                const struct cudaChannelFormatDesc * desc,
                                size_t  width,
                                size_t  height = 0,
                                unsigned int flags = 0);
    struct cudaChannelFormatDesc {
        int x, y, z, w;                 //每個通道的位數
        enum cudaChannelFormatKind f;   //通道的數據類型
    };
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章