cuda统一内存和指针别名

cuda统一内存和指针别名,cuda,Cuda,我正在用cuda刷新我的头脑,特别是unify memory(我上一次真正的cuda开发是在3年前),我有点生锈了 pb: 我正在使用统一内存从容器创建任务。然而,经过几天的调查,我遇到了一次车祸, 我不能说崩溃在哪里(复制构造函数),但不能说为什么。因为所有指针都已正确分配 我与Nvidia post()没有合同 关于C++和统一内存< /p> #include <cuda.h> #include <cstdio> template<class T> st

我正在用cuda刷新我的头脑,特别是unify memory(我上一次真正的cuda开发是在3年前),我有点生锈了

pb:

我正在使用统一内存从容器创建任务。然而,经过几天的调查,我遇到了一次车祸, 我不能说崩溃在哪里(复制构造函数),但不能说为什么。因为所有指针都已正确分配

我与Nvidia post()没有合同 关于C++和统一内存< /p>
#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;
}
#包括
#包括
模板
结构容器{
容器(int size=1){cudamalocmanaged(&p,size*sizeof(T));}
~container(){cudaFree(p);}
__设备uuuuuuu主机uuuuuu与运算符[](inti){返回p[i];}
T*p;
};
结构任务{
int*a;
};
__全局无效内核gpu(任务与t、容器与v){
printf(“gpu值任务%i,应该是2\n”,*(t.a));//这项工作
任务tmp(v[0]);//错误
printf(“来自向量%i的gpu值任务,应该是1\n”,*(tmp.a));
}
无效内核_cpu(任务与t、容器与v){
printf(“cpu值任务%i,应该是2\n”,*(t.a));//这项工作
任务tmp(v[0]);
printf(“来自向量%i的cpu值任务,应该是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;
任务t1,t2;
t1.a=p1;
t2.a=p2;
容器c(2);
c[0]=t1;
c[1]=t2;
//gpu不工作
内核gpu(c[1],c);
cudaDeviceSynchronize();
//cpu应该工作,没有并发访问
内核cpu(c[1],c);
printf(“工作完成!\n”);
cudaFree(p1);
cudaFree(p2);
返回0;
}
客观地说,我可以将一个对象作为一个参数传递,在这个参数中,内存已被正确分配。然而,看起来不可能使用二级 间接性(此处为容器)

我犯了一个概念上的错误,但我不知道在哪里

最好的

蒂莫卡夫


我的机器:cuda 7.5、gcc 4.8.2、特斯拉K20 m

虽然内存被分配为统一内存,但容器本身在主机代码中声明并在主机内存中分配:
容器c(2)。您不能将其作为对设备代码的引用传递,在内核中取消引用它很可能会导致非法内存访问


您可能希望使用
cuda memcheck
来识别此类问题。

好,但为什么它适用于任务(第一个参数)?。任务对象分配在主机上,外部内存使用cuda统一,最坏情况下,我使用向量及其运算符[]传递任务。您的
任务t1
是[因此很好。但是您的容器不是,因为它有一个自定义析构函数,所以它违反了[析构函数]使您的容器不可平凡复制。正是因为平凡复制,我们才可以将指针(在主机代码中声明,但填充了设备上分配的内存)传递到内核。嗯,您认为我是否可以实现复制/分配/(并可能移动)构造函数,我应该有一些工作?我不确定这一点,因为我从未尝试过。请随时进行实验,并让我知道结果。谢谢!您的
任务
类没有一个构造函数允许它在GPU上正确工作。