不允许从 __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__函数来编译推力集差异
__shared__ 变量可以封装在 __device__ __host__ 函数中吗?