Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么CUDA在访问类成员时崩溃?_C++_Oop_Cuda - Fatal编程技术网

C++ 为什么CUDA在访问类成员时崩溃?

C++ 为什么CUDA在访问类成员时崩溃?,c++,oop,cuda,C++,Oop,Cuda,如果这是一个新问题,很抱歉,但我找不到它。我一直在编写一个可以使用CDUA加速的程序。然而,我的方法在很大程度上依赖于将类对象(完全,而不仅仅是它们的成员)传递给内核来实现功能。为了确定这是否可行,我编写了一个小测试程序 class bulkArray { public: double* value; int xSize; bulkArray(int xSize) { value = new double[xSize]; this->

如果这是一个新问题,很抱歉,但我找不到它。我一直在编写一个可以使用CDUA加速的程序。然而,我的方法在很大程度上依赖于将类对象(完全,而不仅仅是它们的成员)传递给内核来实现功能。为了确定这是否可行,我编写了一个小测试程序

class bulkArray {
public:
    double* value;
    int xSize;

    bulkArray(int xSize) {
        value = new double[xSize];
        this->xSize = xSize;
    }
};

__global__ void addArrays(bulkArray *a, bulkArray *b, bulkArray *c, int N) {
    int id = blockIdx.x*blockDim.x + threadIdx.x;

    if (id < N)
        c->value[id] = a->value[id] + b->value[id];
}

int main() {
    int N = 50000000;

    bulkArray *a;
    bulkArray *b;
    bulkArray *c;

    a = new bulkArray(N);
    b = new bulkArray(N);
    c = new bulkArray(N);

    // allocate unified memory.
    cudaMallocManaged(&a, sizeof(a));
    cudaMallocManaged(&b, sizeof(b));
    cudaMallocManaged(&c, sizeof(c));

    // init vectors on host.
    for (int i = 0; i < N; i++) {
        // CRASHING HERE.
        a->value[i] = sin(i) * cos(i);
        b->value[i] = sin(i) * cos(i);
    }

    int blockSize = 1024;
    int gridSize = (int)ceil((float)N / blockSize);

    addArrays << <gridSize, blockSize >> > (a, b, c, N);

    // sum up vector c.
    double sum = 0;
    for (int i = 0; i < N; i++) {
        sum += c->value[i];
    }

    cout << "Final result: " << sum << endl;

    cudaFree(a);
    cudaFree(b);
    cudaFree(c);

    return 0;
}
类数组{
公众:
双*值;
int-xSize;
bulkArray(int-xSize){
值=新的双精度[xSize];
这->xSize=xSize;
}
};
__全局无效添加数组(bulkArray*a、bulkArray*b、bulkArray*c、int N){
int id=blockIdx.x*blockDim.x+threadIdx.x;
if(idvalue[id]=a->value[id]+b->value[id];
}
int main(){
整数N=50000000;
阵列*a;
阵列*b;
阵列*c;
a=新的阵列(N);
b=新的阵列(N);
c=新的阵列(N);
//分配统一内存。
cudaMallocManaged(a,sizeof(a));
CudamallocManager(b&b,sizeof(b));
CudamallocManager(c&c,sizeof(c));
//主机上的初始化向量。
对于(int i=0;i值[i]=sin(i)*cos(i);
b->值[i]=sin(i)*cos(i);
}
int blockSize=1024;
int gridSize=(int)cell((float)N/blockSize);
添加数组>(a、b、c、N);
//求向量c的和。
双和=0;
对于(int i=0;i值[i];
}

cout您可能对托管内存或
cudamalocmanaged
的工作原理有一些误解。在某些方面,
cudamalocmanaged
在概念上类似于C-library
malloc
,只是它分配托管内存。有关在简单的CUDA应用程序中使用托管内存的更详细介绍,请参见你可以参考一下

具体而言,您的代码存在以下一些问题:

  • 当为具有嵌入式指针的对象数组使用托管分配时,如果您打算在设备上使用托管分配,则所有级别的分配都需要替换为托管分配。因此,如果您想访问设备代码中的该成员/字段,则在构造函数中使用
    new
    ,将不起作用。我们可以替换
    cudamalocmanaged

  • 我们不使用
    new
    分配指针,然后使用
    cudamalocmanaged
    重新分配同一指针

  • C(或C++)中的
    sizeof
    函数在指针上使用时将返回该指针的大小,而不是它指向的任何对象的大小。因此,这不是为对象数组进行分配的合理方法

  • CUDA内核启动是异步的,因此在内核启动之后,如果您想使用托管数据,就必须创建某种类型的同步

  • 以下是解决上述问题的一组最小修改。我省略了适当的CUDA错误检查,但我强烈建议在开发CUDA代码时使用。如果您有困难,我还建议使用
    CUDA memcheck
    运行此代码:

    $ cat t51.cu
    #include <iostream>
    using namespace std;
    class bulkArray {
    public:
        double* value;
        int xSize;
    
        void init(int xSize) {
            cudaMallocManaged(&value, xSize*sizeof(double));
            this->xSize = xSize;
        }
    };
    
    __global__ void addArrays(bulkArray *a, bulkArray *b, bulkArray *c, int N) {
        int id = blockIdx.x*blockDim.x + threadIdx.x;
    
        if (id < N)
            c->value[id] = a->value[id] + b->value[id];
    }
    
    int main() {
        int N = 50000;
    
        bulkArray *a;
        bulkArray *b;
        bulkArray *c;
    
        // allocate unified memory.
        cudaMallocManaged(&a, sizeof(bulkArray));
        cudaMallocManaged(&b, sizeof(bulkArray));
        cudaMallocManaged(&c, sizeof(bulkArray));
        a->init(N);
        b->init(N);
        c->init(N);
        // init vectors on host.
        for (int i = 0; i < N; i++) {
            a->value[i] = sin(i) * cos(i);
            b->value[i] = sin(i) * cos(i);
        }
    
        int blockSize = 1024;
        int gridSize = (int)ceil((float)N / blockSize);
    
        addArrays << <gridSize, blockSize >> > (a, b, c, N);
        cudaDeviceSynchronize();
        // sum up vector c.
        double sum = 0;
        double sum2 = 0;
        for (int i = 0; i < N; i++) {
            sum += c->value[i];
            sum2 += a->value[i] + b->value[i];
        }
    
        cout << "Final result: " << sum << " should be: " << sum2 <<  endl;
    
        cudaFree(a);
        cudaFree(b);
        cudaFree(c);
    
        return 0;
    }
    $ nvcc -arch=sm_35 -o t51 t51.cu
    $ cuda-memcheck ./t51
    ========= CUDA-MEMCHECK
    Final result: 0.624013 should be: 0.624013
    ========= ERROR SUMMARY: 0 errors
    $
    
    $cat t51.cu
    #包括
    使用名称空间std;
    类块阵列{
    公众:
    双*值;
    int-xSize;
    void init(int-xSize){
    cudaMallocManaged(&value,xSize*sizeof(double));
    这->xSize=xSize;
    }
    };
    __全局无效添加数组(bulkArray*a、bulkArray*b、bulkArray*c、int N){
    int id=blockIdx.x*blockDim.x+threadIdx.x;
    if(idvalue[id]=a->value[id]+b->value[id];
    }
    int main(){
    int N=50000;
    阵列*a;
    阵列*b;
    阵列*c;
    //分配统一内存。
    cudaMallocManaged(&a,sizeof(bulkArray));
    CudamAllocManager(&b,sizeof(bulkArray));
    cudaMallocManaged(&c,sizeof(bulkArray));
    a->init(N);
    b->init(N);
    c->init(N);
    //主机上的初始化向量。
    对于(int i=0;i值[i]=sin(i)*cos(i);
    b->值[i]=sin(i)*cos(i);
    }
    int blockSize=1024;
    int gridSize=(int)cell((float)N/blockSize);
    添加数组>(a、b、c、N);
    cudaDeviceSynchronize();
    //求向量c的和。
    双和=0;
    双sum2=0;
    对于(int i=0;i值[i];
    sum2+=a->值[i]+b->值[i];
    }
    
    cout您可能对托管内存或
    cudamalocmanaged
    的工作原理有一些误解。在某些方面,
    cudamalocmanaged
    在概念上类似于C-library
    malloc
    ,只是它分配托管内存。有关在简单的CUDA应用程序中使用托管内存的更详细介绍,请参见你可以参考一下

    具体而言,您的代码存在以下一些问题:

  • 当为具有嵌入式指针的对象数组使用托管分配时,如果您打算在设备上使用托管分配,则所有级别的分配都需要替换为托管分配。因此,如果您想访问设备代码中的该成员/字段,则在构造函数中使用
    new
    ,将不起作用。我们可以替换
    cudamalocmanaged

  • 我们不使用
    new
    分配指针,然后使用
    cudamalocmanaged
    重新分配同一指针

  • C(或C++)中的
    sizeof
    函数在指针上使用时将返回该指针的大小,而不是它指向的任何对象的大小。因此,这不是为对象数组进行分配的合理方法

  • CUDA内核启动是异步的,因此在内核启动之后,如果您想使用托管数据,就必须创建某种类型的同步

  • 以下是解决上述问题的一组最小修改。我省略了适当的CUDA错误检查,但我强烈建议在开发CUDA代码时使用。如果您有困难,我还建议使用
    CUDA memcheck
    运行此代码:

    $ cat t51.cu
    #include <iostream>
    using namespace std;
    class bulkArray {
    public:
        double* value;
        int xSize;
    
        void init(int xSize) {
            cudaMallocManaged(&value, xSize*sizeof(double));
            this->xSize = xSize;
        }
    };
    
    __global__ void addArrays(bulkArray *a, bulkArray *b, bulkArray *c, int N) {
        int id = blockIdx.x*blockDim.x + threadIdx.x;
    
        if (id < N)
            c->value[id] = a->value[id] + b->value[id];
    }
    
    int main() {
        int N = 50000;
    
        bulkArray *a;
        bulkArray *b;
        bulkArray *c;
    
        // allocate unified memory.
        cudaMallocManaged(&a, sizeof(bulkArray));
        cudaMallocManaged(&b, sizeof(bulkArray));
        cudaMallocManaged(&c, sizeof(bulkArray));
        a->init(N);
        b->init(N);
        c->init(N);
        // init vectors on host.
        for (int i = 0; i < N; i++) {
            a->value[i] = sin(i) * cos(i);
            b->value[i] = sin(i) * cos(i);
        }
    
        int blockSize = 1024;
        int gridSize = (int)ceil((float)N / blockSize);
    
        addArrays << <gridSize, blockSize >> > (a, b, c, N);
        cudaDeviceSynchronize();
        // sum up vector c.
        double sum = 0;
        double sum2 = 0;
        for (int i = 0; i < N; i++) {
            sum += c->value[i];
            sum2 += a->value[i] + b->value[i];
        }
    
        cout << "Final result: " << sum << " should be: " << sum2 <<  endl;
    
        cudaFree(a);
        cudaFree(b);
        cudaFree(c);
    
        return 0;
    }
    $ nvcc -arch=sm_35 -o t51 t51.cu
    $ cuda-memcheck ./t51
    ========= CUDA-MEMCHECK
    Final result: 0.624013 should be: 0.624013
    ========= ERROR SUMMARY: 0 errors
    $
    
    $cat t51.cu
    #包括
    使用namespac