thrust::host 执行策略的分段错误

Segmentation fault for thrust::host execution policy

我尝试将数据从主机复制到设备并返回,但不是使用 CUDA API,而是使用 thrust 库。我在 thrust::host_vector 中分配了内存,并尝试将其复制到 thrust::device_vector 中。但是,当对来自主机 <-> 设备的任何数据传输使用 thrust::copythrust::host 执行策略时,程序会因分段错误而崩溃。 Cuda-memcheck 提供以下错误消息:

Error: process didn't terminate successfully
The application may have hit an error when dereferencing Unified Memory from the host.

关于 thrust::host 和 thrust::device 执行策略的实际作用以及使用它们时要考虑哪些约束的文档非常稀少。

thrust::copy 无法使用 thrust::host 执行策略的潜在原因是什么? 请注意,不明确指定参数可以正常工作。我正在使用的机器是 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::copy 在主机和设备之间复制数据时,您不应使用 thrust::hostthrust::device 的执行策略。

通过阅读 thrust::device 的文档(例如)可以很明显地看出其中的原因。

Instead of relying on implicit algorithm dispatch through iterator system tags, users may directly target algorithm dispatch at Thrust's device system by providing thrust::device as an algorithm parameter.

thrust::host

提供了类似的措辞和意图

当然,在主机和设备之间复制数据时,这不是您想要的。您依赖于对迭代器的检查来确定传输方向等。传递 thrust::host 意味着 thrust 可以解释两个地址(最终迭代器被减少为复制操作使用的地址),就好像它们是有效的主机地址一样,因此执行 host->host 复制。如果这些地址之一是设备地址,则会导致段错误。

传递 thrust::device 意味着 thrust 可以将两个地址解释为有效的设备地址,因此执行设备->设备复制。如果这些地址之一是主机地址,那将导致无效参数错误或非法地址错误(如果通过内核实现复制。在我的测试中我碰巧看到了非法地址错误)。

以上肯定是我希望在非 Power9 系统上看到的行为。如果您认为您应该在 Power9 系统上看到一些不同的东西,您可能希望提交一个推力问题。但是,无论平台如何,为该算法传递执行策略对我来说都是荒谬的。