【问题标题】:Segmentation fault for thrust::host execution policy推力::主机执行策略的分段错误
【发布时间】:2020-12-25 05:30:36
【问题描述】:

我尝试将数据从主机复制到设备并返回,但不是使用 CUDA API 而是推力库。我在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)

【问题讨论】:

  • 如果没有看到minimal reproducible example,您的问题将无法得到合理的回答。发生这种情况的潜在原因有很多。请发布一些将您的问题重现到您的问题中的代码。
  • @πάνταῥεῖ 你说得对,我现在更新了问题以包含这样的示例代码。

标签: c++ cuda thrust


【解决方案1】:

在使用thrust::copy 在主机和设备之间复制数据时,不应使用thrust::hostthrust::device 的执行策略。

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

用户可以通过提供thrust::device作为算法参数,直接针对Thrust的设备系统进行算法调度,而不是依赖于通过迭代器系统标签的隐式算法调度。

thrust::host 提供了类似的措辞和意图

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

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

以上当然是我希望在非 Power9 系统上看到的行为。如果您认为您应该在 Power9 系统上看到不同的东西,您可能希望提交一个推力问题。然而,不管平台如何,为这个算法传递一个执行策略对我来说似乎是荒谬的。

【讨论】:

  • 但是,当使用thrust::device 作为数据从设备传回主机的执行策略时,我不仅没有看到段错误,而且实际上观察到了性能提升。跨度>
  • 但这可能是 POWER9 机器上的一个错误,因为我实际上在其他 aws 机器上得到了thrust::device exec 策略的段错误。
猜你喜欢
  • 1970-01-01
  • 2021-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多