Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/139.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在函数中使用多态函子_C++_Cuda_Thrust - Fatal编程技术网

C++ 在函数中使用多态函子

C++ 在函数中使用多态函子,c++,cuda,thrust,C++,Cuda,Thrust,我需要一个函数来计算GPU上几个变量的“数学”函数。我决定使用推力及其zip_迭代器将变量打包到一个元组中,并将我的数学函数作为每个的函数foκ。但我想有一个通用函数,可以计算不同的“数学”函数。所以,我需要在函数中传递这个函子 我认为,要完成这项任务,我应该使用不同版本的operator()(Tuple t)实现一些简单的函子层次结构(只有基类)。例如,函子可以如下所示: struct Func { template <typename Tuple> __host_

我需要一个函数来计算GPU上几个变量的“数学”函数。我决定使用推力及其
zip_迭代器
将变量打包到一个元组中,并将我的数学函数作为每个的函数foκ
。但我想有一个通用函数,可以计算不同的“数学”函数。所以,我需要在函数中传递这个函子

我认为,要完成这项任务,我应该使用不同版本的
operator()(Tuple t)
实现一些简单的函子层次结构(只有基类)。例如,函子可以如下所示:

struct Func {
    template <typename Tuple>
    __host__ __device__
    void operator()(Tuple arg) {
        thrust::get<1>(arg) = 0;
    }
};

strust f1 : public Func {
   ...
};

strust f2 : public Func {
   ...
};

但是有了这样的定义,我就不能把
f1
f2
传递到它里面。我如何正确定义它

您似乎希望将用户定义或用户可选择的函数传递给推力,以便在函子中进行计算。基于这一点,我认为一个可能的答案是非常相似的张贴,但我会提出一些其他意见

  • 我不认为你真的在问这个问题,但我认为用主机类表示,最终将对象传递给设备以在
    推力::设备_向量
    中使用基本上是不可能的,因为尽管这并不完全明显,如果我在主机上创建了一个适当的对象数组,然后尝试在
    asch::device\u vector
    中以多态方式使用它们,这实际上就是我要做的事情。至少,我不能在丛林中挣扎。当然,您可以在设备代码中使用多态性,前提是在设备上正确创建了对象,以便可以正确分配它们的虚拟函数表。可能也有兴趣。如果您想查看在设备对象上使用多态性的示例,请查看我的答案。它演示了使用对象本身定义要在其上执行的函数的思想。(不过,我还是不认为你是这么想的。)
  • 根据您编辑的问题,您似乎希望传递函数的地址,以便在函子中使用。这对于CUDA来说也是不可能的(至少以一种直截了当的方式),因为这种限制可以通过调用“初始化内核”来解决,该内核填充设备函数指针表以用于设备代码,但我认为最终效果并不比我在下面第3节中提出的好
  • 您可以传递用户可选择的函数索引,以便在设备代码中使用 下面的示例演示了最后一个想法:

    #include <thrust/device_vector.h>
    #include <thrust/sequence.h>
    #include <thrust/copy.h>
    #include <thrust/for_each.h>
    #include <thrust/iterator/zip_iterator.h>
    #include <iostream>
    #include <math.h>
    
    
    __host__ __device__ float f1(float x)
    {
      return sinf(x);
    }
    
    __host__ __device__ float f2(float x)
    {
      return cosf(x);
    }
    
    
    
    struct select_functor
    {
      unsigned fn;
    
      select_functor(unsigned _fn) : fn(_fn) {};
      template <typename Tuple>
      __host__ __device__
      void operator()(const Tuple &t) {
        if (fn == 1) thrust::get<1>(t)  = f1(thrust::get<0>(t));
        else if (fn == 2) thrust::get<1>(t)  = f2(thrust::get<0>(t));
        else thrust::get<1>(t) = 0;
      }
    };
    
    
    int main(void)
    {
      unsigned ufn = 1;
      const unsigned N = 8;
      thrust::device_vector<float> data(N), result(N);
      // initilaize to some values
      thrust::sequence(data.begin(), data.end(),  0.0f, (float)(6.283/(float)N));
      std::cout<< "x: " << std::endl;
      thrust::copy(data.begin(), data.end(), std::ostream_iterator<float>(std::cout, " "));
      thrust::for_each(thrust::make_zip_iterator(thrust::make_tuple(data.begin(), result.begin())),thrust::make_zip_iterator(thrust::make_tuple(data.end(),result.end())),select_functor(ufn));
      std::cout<< std::endl << "sin(x): " << std::endl;
      thrust::copy(result.begin(), result.end(), std::ostream_iterator<float>(std::cout, " "));
      ufn = 2;
      thrust::for_each(thrust::make_zip_iterator(thrust::make_tuple(data.begin(), result.begin())),thrust::make_zip_iterator(thrust::make_tuple(data.end(),result.end())),select_functor(ufn));
      std::cout<< std::endl << "cos(x): " << std::endl;
      thrust::copy(result.begin(), result.end(), std::ostream_iterator<float>(std::cout, " "));
      std::cout<< std::endl;
      return 0;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    __主机设备浮点f1(浮点x)
    {
    返回sinf(x);
    }
    __主机设备浮点数f2(浮点数x)
    {
    返回cosf(x);
    }
    结构选择函数
    {
    未签名的fn;
    选择_函子(无符号_-fn):fn(_-fn){};
    模板
    __主机设备__
    void运算符()(常量元组(&t){
    如果(fn==1)推力::get(t)=f1(推力::get(t));
    如果(fn==2)推力::get(t)=f2(推力::get(t));
    else推力::get(t)=0;
    }
    };
    内部主(空)
    {
    无符号ufn=1;
    常数无符号N=8;
    推力::设备_矢量数据(N),结果(N);
    //初始化为某些值
    推力:序列(data.begin(),data.end(),0.0f,(float)(6.283/(float)N));
    
    std::coutHow您将如何确定在特定场景中要使用的特定“math”函数?我想您需要将函数传递(或标识)给functor,而不是反过来。我认为我可以实现所需的“math”函数作为函子,并实现一个函数,该函数为给定向量的每个元素计算此
    math
    函数。因此,此函数是通用的,但应将
    math
    函数(实现为函子)传递给它。您将(必须)将一个函子传递到
    推力::for_each
    。如果要传递单个(单独)假设你想对每个元素应用相同的数学函数,那么我不知道困难是什么。如果你想为每个元素传递不同的函子,你不能这样做。但是如果你想为每个元素传递相同的函子,但是(可能)有每个元素都有不同的数学计算,这是可能的,但你必须有一些方法,一个元素一个元素地确定你想要计算的内容。我认为你的问题不清楚。谢谢@Robert。我编辑了我的帖子并插入了一些代码。我打算为每个元素传递单独的函子。你现在展示的内容并不复杂k和我一样。你只是想把一个函数指针传递给一个函子。此外,你所展示的并不是要为向量的每个元素传递一个单独的函子(或函数指针)。看起来你想应用相同的函数(例如
    func
    )感谢你,罗伯特,你的建议非常有用!
    #include <thrust/device_vector.h>
    #include <thrust/sequence.h>
    #include <thrust/copy.h>
    #include <thrust/for_each.h>
    #include <thrust/iterator/zip_iterator.h>
    #include <iostream>
    #include <math.h>
    
    
    __host__ __device__ float f1(float x)
    {
      return sinf(x);
    }
    
    __host__ __device__ float f2(float x)
    {
      return cosf(x);
    }
    
    
    
    struct select_functor
    {
      unsigned fn;
    
      select_functor(unsigned _fn) : fn(_fn) {};
      template <typename Tuple>
      __host__ __device__
      void operator()(const Tuple &t) {
        if (fn == 1) thrust::get<1>(t)  = f1(thrust::get<0>(t));
        else if (fn == 2) thrust::get<1>(t)  = f2(thrust::get<0>(t));
        else thrust::get<1>(t) = 0;
      }
    };
    
    
    int main(void)
    {
      unsigned ufn = 1;
      const unsigned N = 8;
      thrust::device_vector<float> data(N), result(N);
      // initilaize to some values
      thrust::sequence(data.begin(), data.end(),  0.0f, (float)(6.283/(float)N));
      std::cout<< "x: " << std::endl;
      thrust::copy(data.begin(), data.end(), std::ostream_iterator<float>(std::cout, " "));
      thrust::for_each(thrust::make_zip_iterator(thrust::make_tuple(data.begin(), result.begin())),thrust::make_zip_iterator(thrust::make_tuple(data.end(),result.end())),select_functor(ufn));
      std::cout<< std::endl << "sin(x): " << std::endl;
      thrust::copy(result.begin(), result.end(), std::ostream_iterator<float>(std::cout, " "));
      ufn = 2;
      thrust::for_each(thrust::make_zip_iterator(thrust::make_tuple(data.begin(), result.begin())),thrust::make_zip_iterator(thrust::make_tuple(data.end(),result.end())),select_functor(ufn));
      std::cout<< std::endl << "cos(x): " << std::endl;
      thrust::copy(result.begin(), result.end(), std::ostream_iterator<float>(std::cout, " "));
      std::cout<< std::endl;
      return 0;
    }