CUDA Thrust的多GPU使用

4
我想使用我的两张图形卡片来进行CUDA Thrust计算。
我有两张图形卡片。单独运行每张卡片都可以正常工作,即使我将两个设备向量存储在std::vector中也是如此。
如果我同时使用两张卡片,循环中的第一次运行可以正常工作并且没有错误。但是在第一次运行后,会出现错误,可能是因为设备指针无效。
我不确定确切的问题是什么,或者如何使用两张卡片进行计算。
最小代码示例:
std::vector<thrust::device_vector<float> > TEST() {
    std::vector<thrust::device_vector<float> > vRes;

    unsigned int iDeviceCount   = GetCudaDeviceCount();
    for(unsigned int i = 0; i < iDeviceCount; i++) {
        checkCudaErrors(cudaSetDevice(i) ); 
        thrust::host_vector<float> hvConscience(1024);

                // first run works, runs afterwards cause errors ..
        vRes.push_back(hvConscience); // this push_back causes the error on exec

    }
    return vRes;
}

执行时的错误信息:

terminate called after throwing an instance of 'thrust::system::system_error'
what():  invalid argument

你是在使用从主机复制还是直接使用主机缓冲区? - huseyin tugrul buyukisik
不太明白您的意思。这段代码是从主机复制到设备。 - dgrat
所以它们不是在 SLI 模式下工作? - huseyin tugrul buyukisik
不,它们不是在 SLI 中。我希望 SLI 不是必需的,因为在我的情况下,计算可以是异步的。 - dgrat
@huseyintugrulbuyukisik:你所询问的内容完全不相关。请尽量保持信号与噪音比的平衡。 - talonmies
1个回答

6
这里的问题在于你试图在不同的GPU上下文之间执行device_vector之间的设备到设备数据拷贝(因为有cudaSetDevice调用)。你可能忽略了以下操作序列:
thrust::host_vector<float> hvConscience(1024);
vRes.push_back(hvConscience);

每次迭代中,从hvConscience执行一个复制(copy)操作。Thrust后端期望源和目标内存位于同一GPU上下文中。但在这种情况下,它们不是,因此会出现错误。

你可能想要做的是使用指向device_vector的指针向量进行操作。例如:

typedef thrust::device_vector< float > vec;
typedef vec *p_vec;
std::vector< p_vec > vRes;

unsigned int iDeviceCount   = GetCudaDeviceCount();
for(unsigned int i = 0; i < iDeviceCount; i++) {
    cudaSetDevice(i); 
    p_vec hvConscience = new vec(1024);
    vRes.push_back(hvConscience);
}

[免责声明:在浏览器中编写的代码,未经编译或测试,使用需自行承担风险]

这种方式只需要在正确的GPU上下文中创建每个向量一次,并复制分配主机指针,不会触发任何跨内存空间的设备端复制。


我认为它失败的原因是在调用push_back()时,向量被重新调整大小。这涉及将已经存在的device_vector复制到新位置。由于该device_vector是使用GPU0创建的,但现在我们在GPU1处进行复制,所以会出现错误。我认为如果在循环之前调用vRes.reserve(iDeviceCount),就不会有问题。 - Zbyl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接