【问题标题】:Cuda C++ kernel using nested method calls of different objectsCuda C++ 内核使用不同对象的嵌套方法调用
【发布时间】:2021-12-29 08:55:11
【问题描述】:

我目前正在开发一个程序,该程序执行我决定使用 Cuda 实现的多个并行和独立计算。详细地说,我想从一个类的方法内部调用一个内核,这似乎是可行的。内核使用被复制到设备内存的“this”指针获取当前状态下调用它的对象。

重要的是要知道这个对象包含一个来自另一个类的对象向量,该向量已经预先在宿主代码中分配。在内核内部,我想在已经声明为 device 代码的向量内的每个对象上调用一个方法。而且这种有点嵌套的方法调用不起作用,因为我返回的不是一个有效的结果向量,而是一个零向量,这表明尽管到目前为止一切都应该与 Cuda 兼容,但有些东西不能正常工作。

有两个类:

//Header of Ding-class
#pragma once
#include<cuda.h>
#include<cuda_runtime.h>
#include<cuda_runtime_api.h>
#include "device_launch_parameters.h"
#include<stdio.h>
#include<iostream>
#include <math.h>
#include "test_klasse.cuh"

class Ding
{
private:
    int index;
    size_t size;
    double* result_vector;
    double prop;
    double result;
    test_klasse* stuff_vector;

public:
    __host__ __device__ Ding(int, size_t);
    __host__ __device__ ~Ding();

    __host__ void calculate_stuff(double);
    __host__ __device__ double get_prop();
    __host__ __device__ double get_result();
    __host__ __device__ double get_value(int);
};

//Source code of Ding-class
#include "Ding.cuh"

__global__ void calculation(Ding* teil, double* result, int size, double coeff) {

    int ii = blockIdx.x * blockDim.x + threadIdx.x;

    if (ii < size){
        result[ii] = (*teil).get_value(ii);
    }
}

__host__ __device__ Ding::Ding(int ind, size_t vec_size) {
    index = ind;
    prop = 1;
    result = 0;
    size = vec_size;

    stuff_vector = (test_klasse*)malloc(size * sizeof(test_klasse));

    result_vector = (double*)malloc(size * sizeof(double));

    for (int ii = 0; ii < size; ii++) {
        result_vector[ii] = 0;
        stuff_vector[ii] = test_klasse::test_klasse(ii, 2 * ii);
    }
}

__host__ __device__ Ding::~Ding() {};

__host__ void Ding::calculate_stuff(double coeff) {
    prop = 1;
    double* d_result;
    int* d_size;
    double sum = 0;
    Ding* d_teil;

    cudaMalloc(&d_teil, sizeof(Ding));
    cudaMalloc(&d_result, size * sizeof(double));
    cudaMalloc(&d_size, sizeof(int));

    cudaMemcpy(d_size, &size, sizeof(int), cudaMemcpyHostToDevice);
    cudaMemcpy(d_teil, this, sizeof(Ding), cudaMemcpyHostToDevice);

    calculation <<< size / 512 + 1, 512 >>> (d_teil, d_result, size, coeff);

    cudaMemcpy(result_vector, d_result, size * sizeof(double), cudaMemcpyDeviceToHost);

    for (int ii = 0; ii < size; ii++) {
        std::cout << result_vector[ii] << std::endl;
        result += result_vector[ii];
    }
}

__host__ __device__ double Ding::get_prop() {
    return prop;
}

__host__ __device__ double Ding::get_result() {
    return result;
}

__host__ __device__ double Ding::get_value(int index) {
    return stuff_vector[index].get_sum();
}

向量“stuff_vector”中的对象所属的“内部”类定义如下:

//Header of test_klasse
#pragma once
#include<cuda.h>
#include<cuda_runtime.h>
#include<cuda_runtime_api.h>
#include "device_launch_parameters.h"

class test_klasse
{
private:
    int a;
    int b;
public:
    __host__ __device__ test_klasse(int, int);
    __host__ __device__ ~test_klasse();
    __host__ __device__ void add(int);
    __host__ __device__ int get_sum();
};

//Source code of test_klasse
#include "test_klasse.cuh"

__host__ __device__ test_klasse::test_klasse(int input_a, int input_b) {
    a = input_a;
    b = input_b;
}

__host__ __device__ test_klasse::~test_klasse() {}

__host__ __device__ void test_klasse::add(int s) {
    a += s;
    b -= s;
}

__host__ __device__ int test_klasse::get_sum() {
    return a + b;
}

最后,主函数只是创建了一个 Ding 类的对象并执行再次调用内核的计算:

#include<stdio.h>
#include<math.h>
#include "Ding.cuh"
#include<iostream>

int main() {
    Ding teil(5, 50);
    //std::cout << "Old result: " << std::endl;
    teil.calculate_stuff(3.1234);
    std::cout << "New result: " << teil.get_result() << std::endl;
    return 0;
}

一切编译都没有错误,只要我调用 Ding 对象的方法将其分配给结果,我就会得到合理的结果。当我在“stuff_vector”的成员上调用方法时,事情开始失败。

有谁知道我目前不知道出了什么问题或 Cuda 计算的哪些限制?

【问题讨论】:

  • malloc 在设备上运行在无法通过标准主机端cudaMemcpy API 访问的运行时堆上分配内存。我很确定如果你做一些错误检查,你至少会看到一些无效的参数错误

标签: c++ object methods cuda


【解决方案1】:

cudaMemcpy(d_teil, this, sizeof(Ding), cudaMemcpyHostToDevice) 只会执行Ding 实例的浅拷贝。 也就是说,this-&gt;stuff_vectord_teil-&gt;stuff_vector 将具有相同的指针值。

但是,由于this-&gt;stuff_vector 指向主机内存,d_teil-&gt;stuff_vector 也将指向相同的主机内存。因此它不能在设备代码中被取消引用。

您的代码中还存在与 CUDA 无关的潜在问题。例如,您将一个类的对象分配给未初始化的内存,这可能会导致非平凡的赋值运算符出错。

    stuff_vector = (test_klasse*)malloc(size * sizeof(test_klasse));

    for (int ii = 0; ii < size; ii++) {
        stuff_vector[ii] = test_klasse::test_klasse(ii, 2 * ii);
    }

【讨论】:

    猜你喜欢
    • 2011-05-24
    • 1970-01-01
    • 2021-12-26
    • 1970-01-01
    • 2021-02-07
    • 2021-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多