【发布时间】:2018-11-03 16:42:48
【问题描述】:
我正在寻找一种方便的设计,以便能够在设备上使用编译时大小未知的类。 只需将此类的一个实例发送到设备,就应该对 cudaMalloc 和 cudaMemcpy 进行一次调用(理想情况下)。
该类的宿主版本如下所示:
Class A {
public:
A(int size) : table(size) {
// some useful initialization of table
}
double get(int i) const {
// return some processed element from table
}
private:
std::vector<int> table;
};
内核:
__global__ void kernel(const A *a){
int idx = threadIdx.x + blockDim.x * blockIdx.x;
a->get(idx); // do something useful with it
}
到目前为止,我设计类的设备版本的方式是这样的:
const int sizeMax = 1000;
Class A {
public:
A(int size) {
// size checking + some useful initialization of table
}
__host__ __device__
double get(int i) const {
//
}
private:
int table[sizeMax];
};
以及客户端代码:
A a(128);
A* da;
cudaMalloc((void**)&da, sizeof(A));
cudaMemcpy(da, &a, sizeof(A), cudaMemcpyHostToDevice);
kernel<<<1, 32>>>(da);
cudaDeviceSynchronize();
cudaFree(da);
这很丑,因为:
- 它不得不使用太大的 sizeMax 来浪费带宽 保持安全
- 类没有关闭修改,sizeMax的值会 不可避免地需要在某个时候提出来
是否有任何其他方法可以以更简洁的方式实现相同的目标,而不会对性能产生负面影响?明确一点,我只需要类的设备版本,第一个版本只是等效的非CUDA代码来说明表大小应该是动态的。
【问题讨论】:
-
1.
table的独立主机和设备存储,包含在类中,两者都是动态分配的。 2. 在构造函数中动态分配表存储大小,而不是在您的客户端代码中。这也可能包括在必要时调整大小。 3. 区分使用数据的主机副本或设备副本(即指针)的类方法,具体取决于方法是在主机代码还是设备代码中执行 4. 将数据从主机复制到的方法设备,反之亦然,因为类上下文从主机移动到设备,反之亦然。 -
@RobertCrovella 在第 2 点,这意味着用户自己实现
std::vector功能?使用thrust::device_vector<int>之类的实现怎么样? -
@BAdhi:不,这意味着在运行时分配一些内存并将该内存的地址分配给结构中的指针,并且没有推力::device_vector 不能使用,因为它不是设备代码支持。
标签: c++ class memory-management dynamic cuda