c++ - 如何将 cudaMallocManaged 与带有构造函数的对象一起使用

标签 c++ cuda

我正在尝试将 CUDA 托管内存与我通过构造函数创建的对象结合使用。

struct A {
    A(float x) : x(x) {}
    float x;
}

__global__ void myKernel(A *a) {
    printf("%f", a->x);
}

int main() {
    A *a;
    cudaMallocManaged(&a, sizeof(A));
    a->x = 42.f;        // This works
    // a = new a(42.f); // This obviously doesn't because a doesn't point
                        // to managed memory now.
    myKernel<<<1,1>>>(a);
}

使用构造函数而不是直接初始化 a->x = ... 对于 A 更复杂的类来说会很方便。

我当然可以使用构造函数创建对象 a 并使用“正常”cudaMalloc 和 cudaMemcpy,如下所示。

A a(42.f);
A *d_a;
cudaMalloc(&d_a, sizeof(A));
cudaMemcpy(d_a, &a, sizeof(A), cudaMemcpyHostToDevice);

是否有可能使用托管内存并仍然使用其构造函数初始化对象?

最佳答案

正如马克·哈里斯 (Mark Harris) 所讨论的那样 here ,您可以为您的类重载 newdelete 运算符,以便通过托管内存 API 分配和释放实例,而不是通过主机标准库内存分配。这样做意味着您无法在设备代码中为以此方式定义的任何类调用 new

为此,一个非常方便的设计模式(再次完全归功于 Mark Harris 博客的想法),是定义一个仅包含合适的 newdelete 的类运算符,然后在定义将使用统一内存的自己的类时继承它。像这样:

class Managed {
public:
  void *operator new(size_t len) {
    void *ptr;
    cudaMallocManaged(&ptr, len);
    cudaDeviceSynchronize();
    return ptr;
  }

  void operator delete(void *ptr) {
    cudaDeviceSynchronize();
    cudaFree(ptr);
  }
};

class A : public Managed
{
public:
    A(float x) : x(x) {}
    float x;
}

// ....

A *a = new A(42.f);

请注意,理想情况下您还应该为数据类定义赋值运算符,以便复制构造和其他有用的 C++ 习惯用法能够正常工作。

关于c++ - 如何将 cudaMallocManaged 与带有构造函数的对象一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48373834/

相关文章:

c++ - GCC 不会根据 SFINAE 规则禁用功能

cuda - 动态并行 - 编译时对 __cudaRegisterLinkedBinary 链接错误的 undefined reference - 单独编译

.net - 加强托管线程和操作系统线程之间的关系(CUDA 用例)

c - 为什么我的内核没有超过共享内存限制?

random - cuRand Mersenne twiner __device__ 侧内核代码示例

c++ - malloc() 用于跟踪分配大小的空间

c++ - WinAPI 函数 Hook 以捕获网络

optimization - 使用 CUDA 进行蒙特卡洛优化

c++ - std::线程问题

c++ - 如何在 C++ 中将字符串作为 shell 脚本执行?