不允许从 __host__ __device__ 函数调用 __host__ 函数

Posted

技术标签:

【中文标题】不允许从 __host__ __device__ 函数调用 __host__ 函数【英文标题】:calling a __host__ function from a __host__ __device__ functon is not allowed 【发布时间】:2021-08-30 03:22:32 【问题描述】:

我正在尝试将推力与 Opencv 类一起使用。最终的代码会更复杂,包括使用设备内存,但这个简单的例子没有成功构建。

#include <thrust/host_vector.h>
#include <thrust/device_vector.h>

//#include <thrust/copy.h>
#include <thrust/remove.h>
#include <cuda.h>
#include <cuda_runtime.h>

#include <opencv2/opencv.hpp>
#include <opencv2/core.hpp>
#include <opencv2/cudaarithm.hpp>

#include <iostream>

struct is_zero

  __host__  __device__ 
  bool operator()(const cv::KeyPoint x)
  
    return x.response  == 0.0;
  
;


int main(void)

cv::KeyPoint h_data[5]; 


h_data[0]=  cv::KeyPoint(cv::Point2f(3,4),0.3);
h_data[1]=  cv::KeyPoint(cv::Point2f(2,6),0.3);
h_data[2]=  cv::KeyPoint(cv::Point2f(1,1),0.3);
h_data[3]=  cv::KeyPoint(cv::Point2f(2,8),0.3);
h_data[4]=  cv::KeyPoint(cv::Point2f(2,6),0.3);


h_data[0].response=0.3;
h_data[1].response=0.0;
h_data[2].response=0.5;
h_data[3].response=0.0;
h_data[4].response=0.6;


cv::KeyPoint *new_data_end = thrust::remove_if(h_data, h_data + 5, is_zero());  //this does not work

 

如您所见,我什至没有将主机内存变量传递给设备内存或其他任何东西。

当我尝试构建时,我得到了

/usr/local/cuda/include/thrust/system/cuda/detail/par.h(141): warning: calling a __host__ function("cv::Point_<float> ::Point_") from a __host__ __device__ function("cv::KeyPoint::KeyPoint") is not allowed

/usr/local/cuda/include/thrust/system/cuda/detail/par.h(141): warning: calling a __host__ function("cv::Point_<float> ::Point_") from a __host__ __device__ function("cv::KeyPoint::KeyPoint [subobject]") is not allowed

/usr/local/cuda/include/thrust/system/cuda/detail/par.h(141): warning: calling a __host__ function("cv::Point_<float> ::operator =") from a __host__ __device__ function("cv::KeyPoint::operator =") is not allowed

如何将推力 remove_if 与 opencv 类一起使用?

(我的计划是将来使用带有 cv::KeyPoint 数组的 remove_if)

【问题讨论】:

请注意,这只是一个警告,对于主机代码中的这种情况,可以忽略它。但是对于您(毫无疑问)最终想到的设备使用情况,您不能,并且警告将变为错误。为此,您需要在设备代码中复制构建主机端对象。这是不允许的。通常,推力算法仅设计用于可轻松构造的 POD 类型和对象。 这很有趣。你认为有一种方法可以对元素为对象的数组进行流压缩吗? 是的,我在第一条评论中也说了这么多。但由于我已经概述的原因,不是 this specific 类。如果该类不是简单可构造的或没有设备构造函数,那么它将无法工作。这似乎是这样一个类。 【参考方案1】:

正如 cmets 中所指出的,对于您显示的代码,您会收到一个警告,并且可以安全地忽略此警告。

用于 CUDA 设备代码:

对于可在 CUDA 设备代码中使用的 C++ 类,将在 CUDA 设备代码中显式或隐式使用的任何相关成员函数,must be marked 和 __device__ 装饰器。 (有一些例外情况,例如这里不适用的默认构造函数。)

您尝试使用的 OpenCV 类 (cv::KeyPoint) 不符合在设备代码中使用的这些要求。它不会按原样使用。

可能有几个选项:

    使用cv::KeyPoint 重铸您的工作,以使用一些提供类似功能的类,您自己编写,以适当设计和装饰的方式。

    也许看看用 CUDA 构建的 OpenCV 是否在这里有替代版本(设计/装饰得当)(我猜它可能没有)

    重写 OpenCV 本身,考虑到所有必要的设计更改,以允许 cv::KeyPoint 类在设备代码中可用。

    作为建议 1 的变体,将相关数据 .response 复制到单独的一组类或只是一个裸数组,然后根据此进行选择工作。在那里完成的选择工作可用于“过滤”原始数组。

【讨论】:

以上是关于不允许从 __host__ __device__ 函数调用 __host__ 函数的主要内容,如果未能解决你的问题,请参考以下文章

不允许通过从__host__ __device__函数调用__host__函数来编译推力集差异

cuda nvcc 使 __device__ 有条件

__shared__ 变量可以封装在 __device__ __host__ 函数中吗?

推力 copy_if:不完整的类型是不允许的

CUDA C Programming Guide 在线教程学习笔记 Part 5

如何修复警告:函数范围的静态 __shared__ 变量不支持动态初始化?