【问题标题】:Transferring an array pointer into CUDA memory via separate class通过单独的类将数组指针传输到 CUDA 内存
【发布时间】:2017-12-12 02:23:09
【问题描述】:

我有一个名为“坐标”的类,它由一个 int 数组指针和一个 bool 变量组成。我想将此指针发送到 CUDA,对其进行修改,然后在 CPU 内存中使用它。

这是 Coordinate.h :

#ifndef __COORDINATE_H
#define __COORDINATE_H

#include <stdlib.h>
#include <cuda.h>

using namespace std;

class Coordinate {

public:
    int *array_pointer;
    bool flag;

    Coordinate() { flag = false; }

    Coordinate(int array_length) {
        flag = false;
        array_pointer = new int[array_length];
        for (int i = 0; i < array_length; i++) {
            array_pointer[i] = -1;
        }
    }
};

#endif

我在 cudamain.cu Check1Check2 中创建了 2 个 global 函数,它们都将 Coordinate 作为参数。 Check1 函数只会改变布尔标志,而 Check2 会改变布尔标志并修改数组

这里是 cudamain.cu :

#include <iostream>
#include <cuda.h>
#include "Coordinate.h"

using namespace std;

__global__ void check1(Coordinate *ptr) {
    c->flag = true;
}

__global__ void check2(Coordinate *c) {
    c->flag = true;
    for (int i = 0; i < 10; i++) {
        c->array_pointer[i] = i;
    }
}


int main() {
    Coordinate *d_a, *d_b, a, b;
    a = Coordinate(10); b = Coordinate(10);

    size_t size = sizeof(Coordinate);

    cudaMalloc((void**)&d_a, size); cudaMalloc((void**)&d_b, size);
    cudaMemcpy(d_a, &a, size, cudaMemcpyHostToDevice); cudaMemcpy(d_b, &b, size, cudaMemcpyHostToDevice);

    check1 << <1, 1 >> > (d_a);
    cudaMemcpy(&a, d_a, size, cudaMemcpyDeviceToHost);
    cout <<"d_a result-> " <<a.flag <<" " <<a.array_pointer[9] << endl;

    check2 << <1, 1 >> > (d_b);
    cudaMemcpy(&b, d_b, size, cudaMemcpyDeviceToHost);
    cout << "d_b result-> " << b.flag << " " << b.array_pointer[9] << endl;
    return 0;
}

我制作了 2 个独立的坐标对象 aba 将与 check1 一起使用,b 将与 check2 一起使用ab 都以相同的方式初始化。

我得到的结果是

d_a result-> 1 -1
d_b result-> 0 -1

预期结果:

d_a result-> 1 -1
d_b result-> 1 9

不同的坐标对象可能有不同的数组长度,所以我无法在坐标类中初始化数组指针。

【问题讨论】:

  • 1.使用proper cuda error checking。 2. 使用cuda-memcheck 运行您的代码。当我这样做时,我看到 check2 内核正在进行非法写访问
  • 具有嵌入式指针的类需要在 CUDA 中进行特殊处理。学习this答案。
  • @RobertCrovella,通过内核访问主机指针是否合法?
  • @SullivanRisk 我相信这个问题和其他问题在我链接的另一个答案中得到了回答。这个问题可以说是那个问题的重复,因为该答案完全涵盖了这种情况(具有嵌入式指针的类)并解释了如何正确管理它。即使除了那个或这个类的例子之外,在设备代码中主机指针不应该被取消引用是一个基本的 CUDA 原则。

标签: c++ arrays pointers cuda


【解决方案1】:

您不能通过取消引用从 CUDA 内核访问主机内存,除非该内存是专门分配的,例如使用cudaMallocManaged()。所以你的程序无法运行。阅读this Parallel4All post 从主机和设备访问相同的内存。另一个alternative 是链接到的@RobertCrovella,涉及分配设备端内存。

但是,坦率地说,我怀疑这两个选项中的任何一个都适合在这种情况下使用,因为名为 Coordinate 的类似乎不需要可变大小的整数数组。你确定像

template <unsigned NumDimensions> 
class Coordinate<N> { 
    std::array<int, NumDimensions> a;  
    // etc. etc.
}

不会?

(请注意,std::array 类本身不能真正用于设备代码,就像大多数标准库一样。但是您可以轻松地 clone std::array 然后在主机端和设备端使用您的 cuda::array 类.)

即使出于某种原因需要动态分配内存,让一个似乎会被多次使用的类分配自己的内存也不是一个好主意。考虑使用一些预先分配的缓冲区并让您的Coordinates 将偏移量提前到其中(尽管这需要同步以确保线程安全,或者使缓冲区线程本地化)。

【讨论】:

  • 您是否尝试过在设备代码中使用std::array 实体?因为我尝试了您展示的内容,但无法正常工作。
  • @RobertCrovella:啊,是的,确实这不起作用,OP 需要将其他内容传递给设备。见编辑
猜你喜欢
  • 1970-01-01
  • 2015-03-26
  • 2012-07-19
  • 2015-03-11
  • 2013-01-25
  • 1970-01-01
  • 2020-01-01
  • 2014-08-14
  • 2010-09-29
相关资源
最近更新 更多