从 cuda 内核中访问类数据成员 - 如何设计正确的主机/设备交互?

2024-01-10

我一直在努力改变一些cuda/C代码变成更面向对象的代码,但以我目前对cuda运行机制的理解来说,我的目标似乎并不容易实现。对于这种情况我也找不到很好的解释。毕竟这可能是不可能的。

我有一个global类的对象myClass保存一个要填充到内核中的数组。

中的方法应该如何myClass定义数组和布尔成员从设备可见然后数组可以是复制回主机?我使用的是 cuda 7.5,我的卡的计算能力是 3.5。

这是描述情况的暂定结构:

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

class myClass
{
public:
        bool bool_var;    // Set from host and readable from device
        int  data_size;   // Set from host
        __device__ __host__ myClass();
        __device__ __host__ ~myClass();
        __host__ void setValues(bool iftrue, int size);
        __device__ void dosomething(int device_parameter);
        __host__ void export();

        // completely unknown methods
        __host__ void prepareDeviceObj();
        __host__ void retrieveDataToHost();
private:
        int *data; // Filled in device, shared between threads, at the end copied back to host for data output
};

__host__ __device__ myClass::myClass()
{
}

__host__ __device__ myClass::~myClass()
{
#ifdef __CUDACC__
        if(bool_var)
                cudaFree(data);
#else
        free(data);
#endif
}

__host__ void myClass::setValues(bool iftrue, int size)
{
        bool_var  = iftrue;
        data_size = size;
}

__device__ void myClass::dosomething(int idx)
{
        int toadd = idx+data_size;
        atomicAdd(&data[idx], toadd); // data should be unique among threads
}


__global__ void myKernel(myClass obj)
{
        const int idx = blockIdx.x*blockDim.x + threadIdx.x;
        if(idx < obj.data_size)
        {
                if(!obj.bool_var)
                        printf("Object is not up to any task here!");
                else
                {
                        printf("Object is ready!");
                        obj.dosomething(idx);
                }
        }
}


myClass globalInstance;

int main(int argc, char** argv)
{
        int some_number = 40;
        globalInstance.setValues(true, some_number);
        globalInstance.prepareDeviceObj();           // unknown
        myKernel<<<1,some_number>>>(globalInstance); // how to pass the object?
        globalInstance.retrieveDataToHost();         // unknown
        globalInstance.export();
        exit(EXIT_SUCCESS);
}

你的方法应该是可行的。当您按值传递对象作为内核参数时(正如您所指出的),实际上不需要进行太多与从主机到设备的传输相关的设置。

您需要在主机和设备上正确分配数据,并使用cudaMemcpy在适当的点键入操作来移动数据,就像在普通 CUDA 程序中一样。

在全局范围内声明对象时需要注意的一件事是,建议这样做not在对象的构造函数或析构函数中使用 CUDA API 调用。原因已涵盖here https://stackoverflow.com/questions/24869167/trouble-launching-cuda-kernels-from-static-initialization-code,我这里就不重复了。尽管这种处理主要集中在 main 之前启动的内核,但 CUDA 延迟初始化也会影响在 main 之外执行的任何 CUDA API 调用main范围,适用于在全局范围内实例化的对象的构造函数和析构函数。

以下是您所展示的一个充实的示例。我基本上没有更改您已经编写的代码,只是为您没有添加的代码添加了一些方法定义。显然这里有很多不同的可能方法。有关更多示例,您可能需要查看CUDA C++集成示例代码 http://docs.nvidia.com/cuda/cuda-samples/index.html#cpp-integration.

这是围绕您所展示的内容的一个有效示例:

$ cat t1236.cu
#include <cstdio>

class myClass
{
public:
        bool bool_var;    // Set from host and readable from device
        int  data_size;   // Set from host
        __host__ myClass();
        __host__ ~myClass();
        __host__ void setValues(bool iftrue, int size);
        __device__ void dosomething(int device_parameter);
        __host__ void export_data();

        // completely unknown methods
        __host__ void prepareDeviceObj();
        __host__ void retrieveDataToHost();
private:
        int *data; // Filled in device, shared between threads, at the end copied back to host for data output
        int *h_data;
};

__host__ myClass::myClass()
{
}

__host__ myClass::~myClass()
{
}

__host__ void myClass::prepareDeviceObj(){
        cudaMemcpy(data, h_data, data_size*sizeof(h_data[0]), cudaMemcpyHostToDevice);
}
__host__ void myClass::retrieveDataToHost(){
        cudaMemcpy(h_data, data, data_size*sizeof(h_data[0]), cudaMemcpyDeviceToHost);
}

__host__ void myClass::setValues(bool iftrue, int size)
{
        bool_var  = iftrue;
        data_size = size;
        cudaMalloc(&data, data_size*sizeof(data[0]));
        h_data = (int *)malloc(data_size*sizeof(h_data[0]));
        memset(h_data, 0, data_size*sizeof(h_data[0]));
}

__device__ void myClass::dosomething(int idx)
{
        int toadd = idx+data_size;
        atomicAdd(&(data[idx]), toadd); // data should be unique among threads
}
__host__ void myClass::export_data(){
        for (int i = 0; i < data_size; i++) printf("%d ", h_data[i]);
        printf("\n");
        cudaFree(data);
        free(h_data);
}


__global__ void myKernel(myClass obj)
{
        const int idx = blockIdx.x*blockDim.x + threadIdx.x;
        if(idx < obj.data_size)
        {
                if(!obj.bool_var)
                        printf("Object is not up to any task here!");
                else
                {
                        //printf("Object is ready!");
                        obj.dosomething(idx);
                }
        }
}


myClass globalInstance;

int main(int argc, char** argv)
{
        int some_number = 40;
        globalInstance.setValues(true, some_number);
        globalInstance.prepareDeviceObj();
        myKernel<<<1,some_number>>>(globalInstance);
        globalInstance.retrieveDataToHost();
        globalInstance.export_data();
        exit(EXIT_SUCCESS);
}
$ nvcc -o t1236 t1236.cu
$ cuda-memcheck ./t1236
========= CUDA-MEMCHECK
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
========= ERROR SUMMARY: 0 errors
$
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

从 cuda 内核中访问类数据成员 - 如何设计正确的主机/设备交互? 的相关文章

随机推荐

  • WPF ListBox WrapPanel 剪辑长组

    我创建了一个列表框来按组显示项目 当组不再适合列表框面板的高度时 它们会从右到左换行 因此 组在列表框中的显示与此类似 其中每个组的高度是任意的 例如 组 1 的高度是组 2 的两倍 1 3 5 4 6 2 以下 XAML 工作正常 因为它
  • malloc 如何与严格别名一起工作 - 它只能在单个编译单元内被违反吗?

    看完之后this https stackoverflow com questions 54237004 strict aliasing rule uint8 t buffer to structure 我有一个类似的问题this one h
  • 在 OSX 和 Mono 上使用 C# 进行开发

    我即将启动一个需要我编写 C 代码的项目 问题是 我有一台 Mac 我想知道在 OSX 10 6 上使用 mono 进行 c 开发是否存在任何陷阱 我认为该页面很清楚 实现很清晰 但另一方面 我读到人们安装 VMWare 或类似的东西来使用
  • 如何提交不更改和新消息?

    我怎样才能制作一个新的commit如果没有对文件进行任何更改 则创建一条新消息 这是不可能的 因为提交的代码 SHA 将是相同的 很少有充分的理由这样做 但参数是 allow empty对于空提交 没有更改文件 与 allow empty
  • Pandas groupby 结合 sklean 预处理续

    从这篇文章继续 Pandas groupby 与 sklearn 预处理相结合 https stackoverflow com questions 42772758 pandas groupby in combination with sk
  • JavaScript 中数组扩展语法的替代方案

    所以我正在使用使用 ES5 JavaScript 的旧代码库 这意味着我无法传播数组 var listOfItems item1 test 1 item2 test2 2 var docDefinition style piecesTabl
  • 如何创建一个有时间限制的哈希/密钥?

    我正在尝试创建一个有时间限制的密钥以在我的一个应用程序中使用 该密钥用于解锁应用程序中的某些功能 到目前为止我的想法是 生成 加密哈希我需要的各种信息 密钥生成日期 验证 加密哈希我需要的各种信息 现在的日期 如果所有信息都相同且日期相同
  • facebook-api:Facebook Connect 跨域接收者 URL 是什么?

    我正在尝试配置我的 Facebook 应用程序可调整大小 文档位于http wiki developers facebook com index php Ressized IFrame http wiki developers facebo
  • 编译时检查特征特化是否具有唯一的 id

    我看过很多帖子解释如何为类生成唯一的 id 就我而言 id 由用户选择 出于各种原因 但我想确保没有 id 在不同的类中使用两次 我将问题简化为以下代码 struct A struct B template
  • html.hidden 未在 asp.net MVC 核心 Razor 视图中设置值

    我正在开发一个 ASP NET MVC 核心应用程序 我有一个带有如下表单元素的弹出窗口 using Html BeginForm AddIVR ITPVoice FormMethod Post new role form Html Hid
  • 应用程序处理错误:意外的 CFBundleExecutable 密钥

    我正在尝试在启用 bitCode 的情况下向 Apple 提交 每次我提交时我都会收到这封电子邮件 我们发现您最近交付的 MyAPPP 存在一个或多个问题 要处理您的交货 必须纠正以下问题 意外CFBundle可执行密钥 Payload M
  • Sass 从模块扩展类

    使用 sass 中的新模块系统 使用 use 而不是 import 我如何在一个文件中定义一个类并使用 extend 在另一个文件中使用它 File 颜色 scss element background color blue 主文件 use
  • 如何将包发布到 TeamCity nuget 服务器?

    我们有一个为 nuget 配置的 TeamCity 7 服务器 它托管在没有外部连接的计算机上 是否可以将包发布到 TeamCity nuget 服务器 例如 如果我们想要将 log4net 包依赖项添加到我们的项目之一 则需要将其发布到
  • 查找数组中大于或等于N的数

    如果我有一个 PHP 数组 array 具有价值观 45 41 40 39 37 31 我有一个变量 number 38 如何返回值 39 因为这是数组中最接近 38 向上计数 的值 Regards taylor
  • 通过 fontforge 脚本获取字形宽度

    为了获取字形宽度 我将TTF字体为AFM 然后解析内容AFM文件来获取每个字形的宽度 由于从技术上来说 fontforge正在从二进制文件中捕获字形宽度TTF文件 然后创建一个AFM字体文件基于AFM标准模板 我想知道是否可以直接转换TTF
  • 如何检查 django 模板中的复选框是否被选中

    我需要检查 django 模板中是否选中了复选框 如果为 False 则打开其他一些字段 我已经尝试过类似的事情 if closed in is closed 但无论复选框是否选中 它们始终为 True 这是我在模板中的复选框属性
  • 如何在c#中获取先前的控制权

    如何在c 中获取先前的控制权 有一种方法可以GetNextControl但没有办法获得先前的控制权 谁能告诉我如何得到这个 提前致谢 GetNextControl Control control bool forward 您可以指定是否要向
  • 将最喜欢的方法添加到 IntelliJ 中的静态导入?

    在 Eclipse 中 可以配置某些 最喜欢的 类 在调用代码完成时将查找这些类 以查看是否可以为方法添加静态导入 这位于首选项 gt Java gt 编辑器 gt 内容辅助 gt 收藏夹 例如 我可以开始输入assertT Eclipse
  • Android CursorLoader,尝试重新查询已经关闭的游标

    我刚刚开始使用新的cursorLoader 但遇到了问题 下面的代码只是为了理解cursorLoader是如何工作的 但我不断得到 当我恢复此活动时 尝试重新查询已关闭的游标 在我开始使用 CursorLoader 之前 该应用程序运行良好
  • 从 cuda 内核中访问类数据成员 - 如何设计正确的主机/设备交互?

    我一直在努力改变一些cuda C代码变成更面向对象的代码 但以我目前对cuda运行机制的理解来说 我的目标似乎并不容易实现 对于这种情况我也找不到很好的解释 毕竟这可能是不可能的 我有一个global类的对象myClass保存一个要填充到内