问题描述
我尝试将数据从主机复制到设备,然后再复制回去,但不是使用CUDA API,而是使用推力库。我在thrust::host_vector
中分配了内存,然后尝试将其复制到thrust::device_vector
中。但是,当将thrust::copy
与thrust::host
执行策略一起用于从主机设备进行的任何数据传输时,程序会因分段错误而崩溃。 Cuda-memcheck提供以下错误消息:
Error: process didn't terminate successfully
The application may have hit an error when dereferencing Unified Memory from the host.
关于push :: host和push ::设备执行策略实际作用以及在使用它们时要考虑哪些约束的文档非常少。
推力::复制不能与推力::主机执行策略一起使用的潜在原因是什么?请注意,未明确指定参数可以正常工作。我正在使用的机器是POWER9机器。
这是一个可复制的小例子:
使用nvcc -O3 -std=c++11 -Xcompiler -fopenmp test.cu -o test
#include <vector>
#include <omp.h>
#include <thrust/copy.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#define NUM_GPUS 4
int main(int argc,char *argv[]) {
size_t num_elements = 10000;
size_t block_size = num_elements/4;
thrust::host_vector<int> hvec(num_elements);
std::vector<thrust::device_vector<int>*> dvecs(NUM_GPUS);
#pragma omp parallel for
for (size_t i = 0; i < NUM_GPUS; ++i)
{
cudaSetDevice(i);
dvecs[i] = new thrust::device_vector<int>(block_size);
thrust::copy( thrust::host,hvec.begin() + (block_size * i),hvec.begin() + (block_size * (i + 1)),dvecs[i]->begin());
}
return 0;
}
nvcc: NVIDIA (R) Cuda compiler driver
Cuda compilation tools,release 10.2,V10.2.89
gcc (GCC) 9.3.1 20200408 (Red Hat 9.3.1-2)
解决方法
使用thrust::host
在主机和设备之间复制数据时,不应使用thrust::device
或thrust::copy
的执行策略。
例如,通过阅读thrust::device的文档可以很清楚地了解其原因。
用户可以不依赖通过迭代器系统标签进行的隐式算法分发,而是可以通过将推力::设备作为算法参数来直接将目标算法分发到Thrust的设备系统。
为thrust::host提供了类似的措辞和意图
当然,这不是在主机和设备之间复制数据时想要的。您需要检查迭代器来确定传输方向等。传递thrust::host
意味着推力可以将两个地址都视为有效的主机地址(最终,迭代器被简化为复制操作使用的地址),因此可以进行host-> host复制。如果这些地址之一是设备地址,则将导致段错误。
传递thrust::device
意味着推力可以将两个地址都解释为有效的设备地址,因此可以进行设备->设备复制。如果这些地址之一是主机地址,则将导致无效的参数错误或非法的地址错误(如果复制是通过内核实现的。在我的测试中,我碰巧看到了非法的地址错误)。
以上肯定是我希望在非Power9系统上看到的行为。如果您认为应该在Power9系统上看到不同的内容,则不妨提出一个重要问题。但是,不管平台如何,为该算法传递执行策略对我来说都是荒谬的。