2016-12-14 51 views
1

我用cuda刷新了我的思想,特別是統一內存(我最後一個真正的cuda dev是3年前),我有點生鏽。cuda統一內存和指針別名

鉛:

我創建使用統一存儲容器的任務。然而,經過幾天的調查,我發現崩潰了, 我不能說崩潰在哪裏(複製構造函數),但不是爲什麼。因爲所有指針都分配正確。

我不與Nvidia的柱(https://devblogs.nvidia.com/parallelforall/unified-memory-in-cuda-6/) 約C++收縮和統一存儲器

#include <cuda.h> 
#include <cstdio> 

template<class T> 
struct container{ 
    container(int size = 1){ cudaMallocManaged(&p,size*sizeof(T));} 
    ~container(){cudaFree(p);} 
    __device__ __host__ T& operator[](int i){ return p[i];} 
    T * p; 
}; 

struct task{ 
    int* a; 
}; 

__global__ void kernel_gpu(task& t, container<task>& v){ 
    printf(" gpu value task %i, should be 2 \n", *(t.a)); // this work 
    task tmp(v[0]); // BUG 
    printf(" gpu value task from vector %i, should be 1 \n", *(tmp.a)); 
} 

void kernel_cpu(task& t, container<task>& v){ 
    printf(" cpu value task %i, should be 2 \n", *(t.a)); // this work 
    task tmp(v[0]); 
    printf(" cpu value task from vector %i, should be 1 \n", *(tmp.a)); 
} 

int main(int argc, const char * argv[]) { 
    int* p1; 
    int* p2; 
    cudaMallocManaged(&p1,sizeof(int)); 
    cudaMallocManaged(&p2,sizeof(int)); 
    *p1 = 1; 
    *p2 = 2; 

    task t1,t2; 
    t1.a=p1; 
    t2.a=p2; 

    container<task> c(2); 

    c[0] = t1; 
    c[1] = t2; 

    //gpu does not work 
    kernel_gpu<<<1,1>>>(c[1],c); 
    cudaDeviceSynchronize(); 

    //cpu should work, no concurent access 
    kernel_cpu(c[1],c); 

    printf("job done !\n"); 

    cudaFree(p1); 
    cudaFree(p2); 

    return 0; 
} 

客觀我可以通過一個對象作爲在存儲器已被正確分配的參數。然而,它看起來像不可能使用間接性(這裏是容器)的第二級

我在做一個概念錯誤,但我不知道在哪裏。

最佳,

Timocafe

我的機器:CUDA 7.5,GCC 4.8.2,特斯拉K20米

+0

你的'任務'類沒有一個構造函數可以讓它在GPU上正常工作。 – talonmies

回答

1

雖然記憶被分配爲統一內存,容器本身是在主機代碼中聲明並分配在主機內存中:container<task> c(2);。您不能將其作爲設備代碼的參考,並且在內核中取消引用它可能會導致非法內存訪問。

您可能需要使用cuda-memcheck來識別此類問題。

+0

好的,但爲什麼它的任務(第一個參數)?任務對象在主機上分配,而使用cuda的外部存儲器統一,最差的是我使用向量及其運算符傳遞任務[] –

+0

你的'任務t1'是[http://en.cppreference.com/w/cpp/concept/TriviallyCopyable](TriviallyCopyable),所以很好。然而你的容器並不像它有一個自定義的析構函數,所以它違反了[http://en.cppreference.com/w/cpp/language/destructor#Trivial_destructor](Trivial destructor)使你的容器不是TriviallyCopyable的要求。 – yhf8377

+0

這是因爲TriviallyCopyable,我們可以將指針(在主機代碼中聲明,但在設備上分配內存填充)傳遞給內核。 – yhf8377