2017-07-07 76 views
0

我有一个名为“Coordinate”的类,它包含一个int数组指针和一个bool变量。我想将这个指针发送到CUDA,修改它,然后将它用在CPU内存中。通过单独的类将数组指针传入CUDA内存

这里是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 检查1CHECK2了2种全球功能,这两者将采取协调作为参数。 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个独立的坐标对象一个b一个将与CHECK1和B去将CHECK2去。 ab以相同的方式被初始化。

结果我得到的是

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

预期结果:

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

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

+2

1.使用[适当的cuda错误检查](https://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime -API)。2.用'cuda-memcheck'运行你的代码。当我这样做时,我发现'check2'内核正在进行非法写入访问 –

+0

带有嵌入式指针的类需要在CUDA中进行特殊处理。研究[this](https://stackoverflow.com/a/15435592/1695960)回答。 –

+0

@RobertCrovella,使用内核访问主机指针是否合法? –

回答

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类主机和设备侧两者上。)

即使由于某种原因需要动态分配内存,但拥有一个看起来会多次使用的类并分配它自己的内存并不是一个好主意。考虑使用一些预先分配的缓冲区,并让你的进程向前移动一个偏移量(尽管这需要线程安全同步,或使缓冲区为线程本地)。

+1

你真的试过在设备代码中使用'std :: array'实体吗?因为我尝试了你所展示的内容,并且无法使其发挥作用。 –

+0

@RobertCrovella:嗯,是的,确实没有用,而OP需要将其他东西传递给设备。请参阅编辑 – einpoklum