我使用thrust
开发了一种算法。我的办公室计算机有一个支持CUDA的卡,具有架构:
---有关设备0的一般信息 名称:Quadro 2000 计算能力:2.1 时钟频率:1251000 kHz 设备重叠: 启用 内核执行超时: 禁用
在这台机器上,我的算法运行没有错误。但是,在尝试生成thrust::system::system_error
时,实验室计算机上的干净构建会引发令人讨厌的device_vector
。这两台机器都运行RedHat 6并且配置相同,但多个图形卡除外。该实验室机器包含三个具有以下体系结构的支持CUDA的卡:
---有关设备0的一般信息 名称:特斯拉C2050 计算能力:2.0 时钟频率:1147000 kHz 设备重叠: 启用 内核执行超时: 禁用
---有关设备1的一般信息 名称:Quadro 2000 计算能力:2.1 时钟频率:1251000 kHz 设备重叠: 启用 内核执行超时: 禁用
---有关设备2的一般信息 名称:Quadro 2000 计算能力:2.1 时钟频率:1251000 kHz 设备重叠: 启用 内核执行超时: Enabled`
我知道thrust
需要针对目标架构进行编译才能工作。因此,我将CUDA设备设置为1
。但是,错误仍然存在。
作为一项调试措施,我在cudaGetDevice()
分配之前立即拨打了device_vector
电话。设备已正确声明为1
。
int device;
CUDA_CHECK_RETURN(cudaGetDevice(&device), __FILE__, __LINE__);
std::cout << "Operating on device " << device << std::endl; // <-- device 1
// copy the turns to the runtime
thrust::device_vector<MalfunctionTurn> d_turns = turns; // <-- error here
我在我的智慧结束时试图调试它。以前有没有人看到这样的错误?更值得注意的是,cudaSetDevice()
是否存在我不知道的限制?我很担心,因为不同机器上的两张相同的卡无法运行相同的代码。
提前致谢。
修改
编译命令行:nvcc -rdc=true -arch=sm_21 -O3 file
以下是重现错误的最小示例:
#define DEVICE __device__
#define HOST __host__
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
template <typename T, std::size_t N>
class Container {
public:
DEVICE HOST
Container() {
}
private:
T data[N];
};
typedef Container<double, 7> double7;
template <std::size_t N = 10 >
class History {
public:
DEVICE HOST
History() {
}
DEVICE HOST
virtual ~History() {
}
private:
double7 history[N];
};
int main() {
try {
thrust::host_vector<History<> > histories(1);
thrust::device_vector<History<> > d_histories = histories;
} catch (const thrust::system_error &) {
std::cerr << "boo boo" << std::endl;
}
return 0;
}
答案 0 :(得分:3)
尽我所知,您的代码(在引擎盖下)违反了对usage of classes with virtual functions的CUDA限制:
不允许将
__global__
函数作为参数传递给具有虚函数的类的对象。
如果我拿走你的代码并删除:
#include <JARSS.h>
并将其替换为:
#define HOST __host__
#define DEVICE __device__
我可以编译它。然而,在引擎盖下,推力执行这一行:
thrust::device_vector<History<> > d_histories = histories;
通过启动一个内核,该内核将主机上的对象作为参数复制到设备中。 (例如,您可以使用nvprof
验证内核启动。)这是推力的常见行为。问题出现在那些具有虚拟析构函数的对象不能以这种方式复制。
与您的问题所述相反,此代码不应在任何CUDA计算机上正确运行。
您可以通过注释掉虚拟析构函数来“修复”您的代码。如果您需要多态行为,那么对实际代码的修复可能会比这更复杂。仍然可以使用具有推力的多态对象行为,请参阅this answer以获得有用的示例。